ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Transferable 찍먹하기
    iOS 2024. 4. 15. 18:59

    안녕하세요. 그린입니다 🍏

    이번 포스팅에서는 이전 SwiftUI의 ShareLink를 학습하면서 나온 Transferable이라는 프로토콜에 대해 학습해보려고 합니다 🙋🏻

     

    어떻게 이 주제에 대해 얘기가 나왔는지 아래 포스팅을 참고하면 알 수 있습니다!
     

    SwiftUI - ShareLink

    안녕하세요. 그린입니다 🍏 이번 포스팅에서는 SwiftUI의 ShareLink에 대해 알아보겠습니다 🙋🏻 사실 예전 포스팅에서 SwiftUI에서 공유 시트를 위한 ActivityView를 사용하는것을 학습한적이 있습니

    green1229.tistory.com

     

    그럼 한번 알아볼까요?


    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에 해당 항목을 포함해야 합니다.

    자세히는 앱의 파일 및 데이터 유형 정의 가이드 문서를 살펴보면 좋을것 같네요!

     

    Defining file and data types for your app | Apple Developer Documentation

    Declare uniform type identifiers to support your app’s proprietary data formats.

    developer.apple.com

     

    또, 만약 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을 담아 전송할 수 없었던것이 이제는 가능해진것이죠.

     


    마무리

    이번 포스팅에서는 찍먹 정도만 가볍게 톺아봤는데, 좀 더 심화적으로 볼 부분이 많더라구요!

    그래서 다음번에 좀 더 심화적인 요 학습을 해볼까 합니다.

     

    Core Transferable | Apple Developer Documentation

    Declare a transfer representation for your model types to participate in system sharing and data transfer operations.

    developer.apple.com

     


    레퍼런스

     

    Transferable | Apple Developer Documentation

    A protocol that describes how a type interacts with transport APIs such as drag and drop or copy and paste.

    developer.apple.com

     

     

    TransferRepresentation | Apple Developer Documentation

    A declarative description of the process of importing and exporting a transferable item.

    developer.apple.com

    'iOS' 카테고리의 다른 글

    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
    UIKit에서 ViewController간 데이터 전달  (95) 2024.01.22
Designed by Tistory.