0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

写真アルバムからTransferableによって画像を取得 (iOS)

Last updated at Posted at 2024-09-29

写真アルバムからTransferableによって画像を取得 (iOS)

Transferableに準拠した画像クラスを以下のように設計しました。自分のアプリできちんと動くように、適宜修正してください。

final class ImageTranseferable: Transferable, Sendable {
    let url: URL

    init(url: URL) {
        self.url = url
    }

    static var transferRepresentation: some TransferRepresentation {
        FileRepresentation(importedContentType: .image) { receivedTransferrable in
            if receivedTransferrable.isOriginalFile {
                return ImageTranseferable(url: receivedTransferrable.file)
            } else {
                let copy = URL.temporaryDirectory.appending(path: "\(UUID().uuidString).\(receivedTransferrable.file.pathExtension)")
                try? FileManager.default.copyItem(at: receivedTransferrable.file, to: copy)
                return ImageTranseferable(url: copy)
            }
        }
    }
}

FileRepresentationを選択した理由は、appleのMeet Transferableで紹介されている下記選択基準によって決めました。

image.png

画像(UIImage)はCodableに準拠しておらず、オンメモリ上に存在するわけでもないので、FileRepresentationを選択しました。

これを使って、UIKitSwiftUIの両方で写真を読み込むようにしていきます。

UIKit

PHPickerViewControllerDelegateで取得したデータをTransferableによってアプリで使えるように

extension ViewController: PHPickerViewControllerDelegate {
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        let itemProvider = results.first!.itemProvider
        if itemProvider.hasRepresentationConforming(toTypeIdentifier: UTType.image.identifier) {
            let _ = itemProvider.loadTransferable(type: ImageTranseferable.self, completionHandler: {
                result in
                switch result {
                case .success(let success):
                    guard let data = try? Data(contentsOf: success.url), let image = UIImage(data: data) else {
                        return
                    }
                    // 何かする。
                case .failure(let failure):
                    // 何かする。
                }
            })
        }
        picker.dismiss(animated: true)
    }
}

SwiftUI

photosPickerで取得したデータをTransferableによってアプリで使えるように

struct ContentView: View {
    @State var isPresented: Bool = false
    @State var items: [PhotosPickerItem] = [] {
        didSet {
            Task {
                var _medias: [Media] = []
                for item in items {
                    let imageRepr = try? await item.loadTransferable(type: ImageTranseferable.self)
                    if let imageRepr, let data = try? Data(contentsOf: imageRepr.url), let image = UIImage(data: data) {
                        _medias.append(.init(id: UUID().uuidString, image: image))
                    }
                }
                self.medias = _medias
            }
        }
    }
    @State var medias: [Media] = []
    var body: some View {
        ScrollView {
            VStack {
                Button(action: {
                    isPresented = !isPresented
                }, label: {
                    Text("写真を開く")
                })
                ForEach(medias) {
                    media in
                    Image(uiImage: media.image!)
                        .resizable()
                        .scaledToFit()
                }
            }
        }
        .photosPicker(isPresented: $isPresented, selection: .init(get: {
            self.items
        }, set: {
            medias in
            self.items = medias
        }), matching: .any(of: [.images]), photoLibrary: .shared())
    }
}

extension ContentView {
    struct Media: Identifiable {
        let id: String
        let image: UIImage?
    }
}

終わりに

めっちゃ書き殴っているので、そのまま自分のアプリに使い回すのはやめてください🙇

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?