-
Transferable 찍먹하기iOS 2024. 4. 15. 18:59
안녕하세요. 그린입니다 🍏
이번 포스팅에서는 이전 SwiftUI의 ShareLink를 학습하면서 나온 Transferable이라는 프로토콜에 대해 학습해보려고 합니다 🙋🏻
어떻게 이 주제에 대해 얘기가 나왔는지 아래 포스팅을 참고하면 알 수 있습니다!
그럼 한번 알아볼까요?
Transferable
우선, WWDC 2022에서 소개된 프로토콜로 iOS 16.0 이상에서 채택하여 사용할 수 있어요!
정의 자체는 타입이 드래그 앤 드롭 혹은 복사 및 붙여넣기와 같은 전송 API와 상호작용하는 방법을 설명하는 프로토콜입니다.
protocol Transferable
심플한 프로토콜같죠?
쉽게 생각해보면 ShareLink를 예시로 떠올려봐도 좋아요.
앱 사이 소통할 수 있는 타입으로 만들기 위해 채택하는것이죠.
ShareLink에서 String, Image, Data, URL 등을 보낼 수 있었던것처럼 해당 타입들은 모두 Transferable 프로토콜을 채택하고 있습니다.
Transferable 프로토콜을 준수하기 위해서는 transferRepresentation 프로퍼티를 구현해야 합니다.
좀 더 자세히 알아보기위해, 공식문서의 예시 코드와 함께 살펴볼께요!
struct ImageDocumentLayer { init(data: Data) func data() -> Data func pngData() -> Data }
해당 코드를 살펴보자면, 이미지 편집 앱의 레이어 타입은 사람들이 문서 내에서 이미지 레이어의 순서를 변경하기 위해 이미지 레이어를 드래그 앤 드롭할 수 있도록 Transferable을 준수하여 구현할 수 있습니다.
즉, 해당 ImageDocumentLayer에 Transferable 프로토콜을 채택하여 구현을 할 수 있다는것이죠.
extension ImageDocumentLayer: Transferable { static var transferRepresentation: some TransferRepresentation { DataRepresentation(contentType: .layer) { layer in layer.data() }, importing: { data in try Layer(data: data) } DataRepresentation(exportedContentType: .png) { layer in layer.pngData() } }
이렇게 확장하여 채택한 후, 필수인 transferRepresentation 프로퍼티를 구현해주는것입니다.
두개로 구성을 해줬는데요.
앱 내 레이어 혹은 사용자 지정 레이어 콘텐츠 타입을 인식하는 다른 앱으로 드래그 앤 드롭을 한다면 해당 앱은 첫번째 DataRepresentation의 구현을 통해 사용합니다.
만약 다른 이미지 편집기에 레이어를 드래그 앤 드롭하면 편집기가 PNG 파일 타입을 인식할 수 있기에 두번째 DataRepresentation에서 PNG 파일에 대한 지원 구현을 추가한것이죠.
extension UTType { static var layer: UTType { UTType(exportedAs: "com.example.layer") } }
해당 코드로 커스텀한 레이어 타입 식별자를 선언해줌으로 사용을 하죠.
주의할점은, 앱에서 해당 커스텀한 사용자 지정 타입 식별자를 선언할때는 앱의 Info.plist에 해당 항목을 포함해야 합니다.
자세히는 앱의 파일 및 데이터 유형 정의 가이드 문서를 살펴보면 좋을것 같네요!
또, 만약 Codable을 준수하는 타입이 있다면 Transferable은 자동으로 데이터로의 변환 및 데이터로부터의 변환을 처리해줍니다.
struct Note: Codable { let title: String let body: String } extension Note: Transferable { static var transferRepresentation: some TransferRepresentation { CodableRepresentation(contentType: .note) } }
CodableRepresentation을 이용하여 해당 타입을 전송가능하게 만들어주죠.
커스텀한 Note 식별자에 대해 모르는 다른 앱과의 호환성을 보장하기 위해서 Note를 title 텍스트로 변환하는 추가 구현을 해야 합니다.
extension Note: Transferable { static var transferRepresentation: some TransferRepresentation { CodableRepresentation(contentType: .note) ProxyRepresentation(\.title) } }
이런식으로 말이죠!
여기서 Representation의 순서가 중요해요.
Note라는 타입 자체를 표현하는 Representation을 가장 먼저 선언하고, 호환 가능하지만 덜 선호되는 Representation을 순서대로 선언해주면 됩니다.
간단히 이렇게 소개할 수 있겠는데요.
앞서 나왔던 필수적인 transferRepresentation 프로퍼티는 항목을 가져오고 내보내는데 사용되는 표현입니다.
@TransferRepresentationBuilder<Self> static var transferRepresentation: Self.Representation { get }
이렇게, 선언이 되어 있는데요.
파고 들어가보면 타입인 Representation은 항목을 가져오고 내보내는데 사용하는 표현 그자체 유형이죠.
associatedtype Representation : TransferRepresentation
TrasnferRepresntation의 associatedType으로 해당 TrasnferRepresntation을 살펴볼께요!
TrasnferRepresntation?
전송 가능한 항목을 가져오고 내보내는 과정에 대한 선언적인 프로토콜입니다.
protocol TransferRepresentation<Item> : Sendable
앞서 살펴봤듯 여러 전송 표현 자체를 결합해서 단일 전송 표현을 구성할 수 있습니다.
import UniformTypeIdentifiers struct Greeting: Codable, Transferable { let message: String var displayInAllCaps: Bool = false static var transferRepresentation: some TransferRepresentation { CodableRepresentation(contentType: .greeting) ProxyRepresentation(exporting: \.message) } } extension UTType { static var greeting: UTType { .init(exportedAs: "com.example.greeting") } }
message 문자열을 통해서 Codable 타입과 Proxy로 전송하는 Greeting 타입을 보여주고 있습니다.
그래서 어떻게 실제적으로 쓰이냐!?
이전 학습한 포스팅에서 예시를 가져와볼께요.
struct Photo: Transferable { static var transferRepresentation: some TransferRepresentation { ProxyRepresentation(exporting: \.image) } public var image: Image public var caption: String }
이렇게 Photo 타입을 선언할때 Transferable 프로토콜을 채택하고 transferRepresentation을 구현해줍니다.
이때 ProxyRepresentation으로 이미지 자체를 익스포팅할 수 있도록 구성하죠.
struct PhotoView: View { let photo: Photo var body: some View { photo.image .toolbar { ShareLink( item: photo, preview: SharePreview( photo.caption, image: photo.image ) ) } }
그리고, ShareLink를 통해 해당 이미지 데이터를 전달할 수 있도록 사용하기만 하면 되는것이죠!
기존에는 photo 자체가 Transferable하지 않았기에 ShareLink를 띄워도 이미지 item을 담아 전송할 수 없었던것이 이제는 가능해진것이죠.
마무리
이번 포스팅에서는 찍먹 정도만 가볍게 톺아봤는데, 좀 더 심화적으로 볼 부분이 많더라구요!
그래서 다음번에 좀 더 심화적인 요 학습을 해볼까 합니다.
레퍼런스
'iOS' 카테고리의 다른 글
UIPasteboard를 통한 클립보드 사용하기 (66) 2024.05.07 Core Transferable 톺아보기 (62) 2024.04.18 TexfField 시뮬레이터 버그 (Timeout) (65) 2024.03.25 What's new in Screen Time API (WWDC 22) (58) 2024.03.18 Meet the Screen Time API (WWDC21) (62) 2024.03.14