SwiftUI

SwiftUI - ShareLink

GREEN.1229 2024. 4. 5. 18:56

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

이번 포스팅에서는 SwiftUI의 ShareLink에 대해 알아보겠습니다 🙋🏻

 

사실 예전 포스팅에서 SwiftUI에서 공유 시트를 위한 ActivityView를 사용하는것을 학습한적이 있습니다.

 

ActivityView in SwiftUI

안녕하세요. 그린입니다🟢 이번 포스팅에서는 SwiftUI에서 ActivityView(액티비티 뷰)를 띄우는것에 대해 학습해보겠습니다💁🏻 SwiftUI를 통해 구현을 하다 어떻게 하면 요런 데이터를 공유할 수 있

green1229.tistory.com

 

이번에 할것도 저 ActivityView를 띄우는것인데요.

차이는, 이전 저 포스팅에서는 SwiftUI에서 직접적으로 지원하지 않아서, UIKit의 ActivityViewController를 사용하여 SwiftUI로 끌어들여와서 했습니다.

 

그런데, 이번에는 SwiftUI에서 지원해주는 ShareLink를 이용해서 구현하는 방법을 알아보시죠 😃


ShareLink?

우선, ShareLink는 앞서 설명했던것처럼 공유 프레젠테이션을 제어하는 뷰입니다.

즉, 우리가 흔히 익숙한 공유 시트라고 생각하면 편할것 같네요.

 

이전 포스팅들에서 다루지 않았던 이유는 해당 기능을 사용하려면 미니멈 타겟이 iOS 16 이상이여야 합니다.

그렇기에, 그때는 대중적인 iOS 미니멈 타겟이 아니였죠.

이제는 슬슬 알아보고 적용해봐도 좋을거라 생각해요!

 

struct ShareLink<Data, PreviewImage, PreviewIcon, Label> where Data : RandomAccessCollection, PreviewImage : Transferable, PreviewIcon : Transferable, Label : View, Data.Element : Transferable

 

선언이 조금 길긴하지만 사용은 어렵지 않아요.

 

일반적인 초기화 메서드를 살펴볼까요?

 

init(
    item: String,
    subject: Text? = nil,
    message: Text? = nil
) where Data == CollectionOfOne<String>

 

정말 단순히 항목만을 공유할때 사용합니다.

item은 공유할 항목이 되고, subject는 항목의 타이틀이며 message는 항목에 대한 설명입니다.

 

사실 이 외에도 미리보기와 함께 항목을 공유한다거나, 레이블과 함께 항목을 공유하거나, 둘다 혼합하여 항목을 같이 공유하거나 등등에 따라 이니셜라이저가 되게 많습니다.

 

 

그렇기에 다 담을수 없어서 어떤 이니셜라이저들이 존재하는지는 공식 문서를 통해 확인해보세요 😃

 

그래서 가장 기본적으로 알아야할것은 우리는 item이라는 매개변수는 어떤 이니셜라이저에도 다 들어가죠?

이 item이 공유하고자 하는 항목입니다.

String이 될수도 URL이 될수도 Data가 될 수도 있죠.

 

그렇기에 ShareLink는 이 item을 공유하는거라 볼 수 있습니다.

 

ShareLink(item: URL(string: "https://developer.apple.com/xcode/swiftui/")!)

 

이렇게 초기화 시켜 구성하면 해당 URL을 공유하는거겠죠?

 

그런데 위에는 저 코드를 그대로 뷰에 얹으면 아래와 같이 나타나요.

 

기본적으로 지정해둔 모양으로 나타나서 저 버튼을 클릭하면 요렇게 공유 시트가 노출됩니다.

 

 

그럼 여기서 기본 제공되는 모양이 아닌 우리가 직접 레이블을 구성해서 그 레이블을 공유링크로 사용할 수도 있다고 했죠?

 

ShareLink(item: URL(string: "https://developer.apple.com/xcode/swiftui/")!) {
    Label("Green ShareLink", systemImage: "circle.fill")
}

 

이렇게 Label을 인자로 담아 Text와 Icon을 지정하여 아래와 같이 공유링크를 만들 수 있습니다.

 

만약 아이콘도 필요없이 Text 형태로 간단히 사용자 정의하여 만드는것도 손쉽게 가능해요.

 

ShareLink("Green ShareLink", item: URL(string: "https://developer.apple.com/xcode/swiftui/")!)

 

이렇게 가능한 이유는 앞서 설명했듯이 정말 수많은 초기화 메서드가 존재하기에 가능합니다.

원하는 형태의 공유 링크를 위해서 각종 형태의 초기화 메서드들을 파악해보고 사용해보면 좋습니다 😄

 

하나 중요한걸 캐치해보자면, item으로 전달할 수 있는것에서 우리는 직접 타입을 만들고 사용할 수도 있습니다.

기존 URL과 같은 특정 타입들은 Transferable이라는 프로토콜을 이미 준수하고 있어서 데이터를 전달할 수 있었는데요.

커스텀한 타입을 만들때 이 Transferable 프로토콜을 준수하면 전송 가능한 객체를 만들 수 있어요.

또한, ProxyRepresentation을 사용하여 타입을 프레임워크 타입으로 변환해 해결할 수도 있습니다.

ProxyRepresentation은 개발자가 정의한 타입을 다른 타입으로 변환하는 역할을 하고 이를 통해서 커스텀하게 만든 타입도 Transferable 프로토콜을 준수하게 만들 수 있죠!

 

예시로 한 스텝씩 살펴볼까요?

 

struct Photo: Transferable {
  static var transferRepresentation: some TransferRepresentation {
    ProxyRepresentation(exporting: \.image)
  }
  
  public var image: Image
  public var caption: String
}

 

이렇게, Photo라는 Transferable 프로토콜을 준수하는 객체 타입을 만들 수 있습니다.

 

그리고, SwiftUI에서 이 Photo를 사용해볼께요.

 

struct PhotoView: View {
  let photo: Photo
  
  
  var body: some View {
    photo.image
      .toolbar {
        ShareLink(
          item: photo,
          preview: SharePreview(
            photo.caption,
            image: photo.image
          )
        )
      }
  }
}

 

이렇게 photo를 사용해 툴바로 ShareLink를 지정하여 item에 photo를 데이터로 전송할 수 있게 되는것이죠!

여기서 공유 시 프리뷰로 photo의 캡션 String과 이미지를 미리보여줍니다.

 

그럼 이 구성을 적용해볼까요?

 

import SwiftUI

struct ContentView: View {
  var body: some View {
    NavigationView {
      PhotoView(photo: .init(image: .init(systemName: "circle.fill"), caption: "green"))
    }
  }
}

 

툴바 메서드는 보통 네비게이션뷰 내 구조에서 사용되기에 감싸줍니다.

이렇게 PhotoView를 부를때 photo를 정의해서 넘겨주죠.

 

그럼 아래와 같이 가운데 원 아이콘이 그려지게 되고 우측 상단에 Share 버튼이 노출됩니다.

 

 

그럼 저 우측 버튼을 누르면, 공유 시트가 뜨게 되죠!

 

 

간단하죠!?

 

만약 앱에서 공유하는 데이터가 즉시 사용 가능하지 않을 때, 예를들면 네트워크 요청 같은 비동기 작업을 통해서 데이터를 검색하여 준비하고 제공해야되는 로직을때 비동기적으로 수행할 수 있습니다.

바로, FileRepresentation과 DataRepresentation을 이용하면 됩니다!

이건 또 다른 포스팅으로 더 심도있게 알아보도록 해요 😃

 

또한, Transferable 타입을 사용한다면 단일 공유 가능 항목에 대해서 여러 콘텐츠 타입을 제공해줄 수 있습니다.

즉, 이미지와 텍스트를 동시에 공유하려는 경우에 사용자에게 이메일 또는 메시지 앱과 같은 적절한 공유 옵션을 제시할 수 있습니다.

 

다음으로는, subject와 message를 어떻게 쓰는지 알아볼까요?

 

struct ContentView: View {
  var body: some View {
    ShareLink(
      item: "https://green1229.tistory.com",
      subject: Text("Green Blog"),
      message: Text("iOS Tech Blog")) {
        Image(systemName: "square.and.arrow.up")
    }
  }
}

 

이렇게 만약 URL을 공유할때 타이틀과 설명을 넣어주기 위해 구성합니다.

그리고, 공유 시트를 통해 공유하려고 한다면 이렇게 나타나죠!

 

 

마지막으로, 이미지 미리보기 및 공유에 대해서 하나 말씀드리면 서버로부터 다운 받거나 직접 에셋에 있는 이미지들은 정상적으로 미리보기가 잘되고 공유도 잘됩니다.

아래처럼 말이죠!

 

import SwiftUI

struct ContentView: View {
  private let photo = Image("cat")
  
  var body: some View {
    ShareLink(item: photo, preview: SharePreview("Cat", image: photo))
  }
}

 

그런데 Xcode에서 기본적으로 내장되어 지원해주는 시스템 아이콘들있죠?

그 아이콘들은 이렇게 정상적이지 않게 보입니다.

 

import SwiftUI

struct ContentView: View {
  private let photo = Image(systemName: "pencil.circle.fill")
  
  var body: some View {
    ShareLink(item: photo, preview: SharePreview("Pencil", image: photo))
  }
}

 

미리보기에서 나타나지 않는것 처럼 보이죠?

아마도 벡터 방식이라 그럴 수 있지 않을까 생각을 했는데....

실제로 시스템 아이콘이 아닌 직접 SVG 파일을 사용해서 테스트해보면 미리보기에서는 잘 뜨더라구요.

(왜인지는 잘 모르겠음 🥲)

 

아무튼, 이 점 유의해서 이미지를 잘 공유해야할것 같아요!


마무리

이렇게 SwiftUI 4.0, iOS 16부터 사용가능한 SwiftUI에 내장된 ShareLink에 대해 알아봤습니다!

ActivityVC를 안써도 될만큼 다 호환되는것 같아요..!

점점 편해지는거 같으면서도 오히려 불편해지는것 같은 이 느낌 😇

 


레퍼런스

 

ShareLink | Apple Developer Documentation

A view that controls a sharing presentation.

developer.apple.com