🐙
プロトコルTransferableへの理解
Transferable
Transferable
はiOS 16から利用可能なプロトコルです。
その名の通り転送可能
であることを示すプロトコルです。
転送可能になることでDrag & DropなどのUI上でアイテムを転送可能にしたりすることができます。
他にもPhotosPickerでTransferable
が使用されています。
Transferableへの理解
Transferableは難しそうですが、ほぼCodableと一緒です。
モデル -> Data
、Data -> モデル
への変換が用意されていれば問題ないです。
実装例(CodableRepresentation)(Codable可能)
struct Person: Codable {
let age: Int
let name: String
}
extension Person: Transferable {
static var transferRepresentation: some TransferRepresentation {
CodableRepresentation(for: Person.self, contentType: .person)
}
}
// Info.plistに独自のUTTypeを登録する必要がある
// 適当にUTType.contentとかを使っても問題ない
extension UTType {
static var person: UTType { UTType(exportedAs: "com.example.person") }
}
実装例(DataRepresentation)
自前でモデル -> Data
、Data -> モデル
の変換処理を実装
struct ImageModel {
let image: UIImage
}
extension ImageModel: Transferable {
static var transferRepresentation: some TransferRepresentation {
DataRepresentation(contentType: .content) { imageModel in
return imageModel.image.pngData()!
} importing: { data in
let uiImage = UIImage(data: data)!
return ImageModel(image: uiImage)
}
}
}
extension UTType {
static var imageModel: UTType { UTType(exportedAs: "com.sample.imageModel") }
}
実装例(FileRepresentation)
Dataで転送(Transfer)するには重すぎるようなモデル(動画など)では、ファイルパスのみを転送することで簡単にTransferableに準拠させることができます。
struct Movie {
let url: URL
}
extension Movie: Transferable {
static var transferRepresentation: some TransferRepresentation {
FileRepresentation(contentType: .movie) { movie in
SentTransferredFile(movie.url)
} importing: { receivedData in
let fileName = receivedData.file.lastPathComponent
let copy: URL = FileManager.default.temporaryDirectory.appendingPathComponent(fileName)
try FileManager.default.copyItem(at: receivedData.file, to: copy)
return .init(url: copy)
}
}
}
extension UTType {
static var movie: UTType { UTType(exportedAs: "com.sample.movie") }
}
実装例(ProxyRepresentation)
すでにTransferable
に準拠ずみのプロパティを設定可能です。
struct Note: Transferable {
var body: String
static var transferRepresentation: some TransferRepresentation {
ProxyRepresentation(exporting: \.body)
}
}
Discussion