SwiftUI を使った イメージ処理アプリを作ってみます
Sponsor Link
環境&対象
以下の環境で動作確認を行なっています。
- macOS Big Sur 11.1
- Xcode 12.3
本シリーズ内容
SwiftUI を使って、イメージ処理するアプリを作ります。
以下の理解が進むことがゴールです。
- SwiftUI を使ったアプリ開発
- NSImage を使った画像処理全般
- Photos 拡張編集機能 と SwiftUI app の組み合わせ方
- イメージ処理アプリも TDD で進めることが可能かどうか
- その他 macOS app 開発 Tips
この記事で作る範囲
最初に、画像の上にメガネを重ねて表示することができました。
その後、メガネをドラッグすることで 位置変更できるようにし、追加で、サイズ変更もできるようにしてきました。
今回は、別の画像の上にメガネを重ねることができるようにします。
一言で言うと、別画像のファイルをドロップすることで、画像を入れ替える機能をつけます。
- 画像ファイルをドロップされたら、その写真を表示する
写真をドロップできるようにする
やること
写真ファイルをドロップすると、その画像を表示できるようにします。
ドロップされる要素への対応は、SwiftUI では onDrop で行うことができます。
テスト
テストが難しいです。
実装機能はシンプルなのですが、外部からファイルをドロップする方法がわかりません・・・・・
Finder で新規ウィンドウを開くことまではできるようになったのですが、特定のフォルダまで移動できないので、ドロップできるファイルまで辿り着けません。
# 方法がわかったら この記事をアップデートします。
なので、今回はテストコードは無しです。
手動でテストすることとします。
テスト項目は、以下を想定します。
「画像ファイル(JPG)をドロップしたら、置き換わる」
「画像ファイル(PNG)をドロップしたら、置き換わる」
「画像でないファイルをドロップしたら、無視される」
アプリ実装
以前の記事でも説明しています。

UITest を作るのは難しいですが、アプリの実装自体は簡単です。
ContentView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
// // ContentView.swift // // Created by : Tomoaki Yagishita on 2021/01/19 // © 2021 SmallDeskSoftware // import SwiftUI import UniformTypeIdentifiers struct MainView: View { @State private var image:NSImage = NSImage(named: "initialPhoto")! @State private var isTargeted = false var body: some View { ZStack { Image(nsImage: image).resizable().scaledToFit().frame(width: 500, height: 500) .accessibility(identifier: "mainImage") // (1) .onDrop(of: [UTType.fileURL], isTargeted: $isTargeted) { (providers) -> Bool in guard let provider = providers.first else { return false } // handle first item only // (2) provider.loadItem(forTypeIdentifier: kUTTypeURL as String, options: nil) { (url, error) in // (3) DispatchQueue.main.async { if let url = url as? Data { // (4) let imageURL = NSURL(absoluteURLWithDataRepresentation: url, relativeTo: nil) as URL if let localImage = NSImage(contentsOf: imageURL) { // (5) image = localImage } } else if let error = error { print(error) } } } return true } GlassImage() } .padding() } } |
コード解説
- .onDrop modifier でドロップを受け取ります
- NSItemProvider の loadItem を使って、ドロップされた情報を受け取ります
- UI 更新が必要となるため、main キューで操作します
- ファイルの URL が渡されるので、そこから NSImage を作ります
- NSImage を作ることができたら、表示イメージにセットします
この記事でできたこと
- イメージのファイルをドロップすることで、画像を置き換える
現在のアプリ
以下のような動作です。
次回
次回以降は 現在の機能を Photos の拡張機能としても使えるようにアプリを変更していきます。
説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。
Sponsor Link