iOS/iOS

[iOS] ShareExtension을 사용해보자 (1) - ShareExtension 생성하기

여성일 2025. 10. 8. 14:30
728x90
ShareExtension ?

역시 모를 땐 애플 가이드 문서를 참고하자..

 쉐어 익스텐션은 iOS에서 제공하는 앱 확장 기능 중 하나로, 사용자가 Safari, 뉴스, 사진, 브라우저 등 다른 앱에서 컨텐츠를 공유할 때, 특정 앱의 기능을 공유 시트 안에서 바로 사용할 수 있게 해주는 기능이다. 

 

 공유 버튼 눌렀을 때 많이들 본 그 시트이다!

 

ShareExtension 생성하기

 Xcode 메뉴바 → File → New → Target → Share Extension을 선택하면 ShareExtension이 생성된다.

 

 ❗️위와 같이 ShareExtension에 대한 스킴을 활성화 할지 물어보데, Activate를 눌러서 활성화 하자. 

 

 정상적으로 활성화가 됐다면 스킴 목록에서 해당 ShareExtension 스킴을 확인할 수 있다. 

 

❓스킴 활성화 하면 뭐가 좋은데요? → 독립적으로 실행과 디버깅이 가능하다! 개발할 땐 활성화 하는게 좋고, 배포할 땐 활성화 안해도 상관 없다.

 

 스킴까지 활성화 하면 ShareExtension이 생성될 것이다. 일단 ShareViewController부터 살펴보자. ShareViewController는

SLComposeServiceViewController를 상속하고 있을 것이다. SLComposeServiceViewController는 ShareExtension을 만들 때 가장 기본이 되는 뷰 컨트롤러 클래스이다. 쉽게 말해, 공유 시트에서 열리는 UI의 기본 뼈대라고 생각하면 된다.

 

 사용자가 Safari나 타앱에서 공유를 눌러 우리 앱을 선택하면 시스템이 자동으로 SLComposeServiceViewController를 띄워준다. 사용자는 제목, 메모 등을 입력하고 Post 버튼을 누르면 로직이 실행된다.

 

SLComposeServiceViewController의 주요 구성 요소

1. contentText : 사용자가 입력한 텍스트

위 처럼 정의되어 있기 때문에, 사용자가 입력한 텍스트에 접근하고 싶으면 contentText에 접근하면 된다.

 

2. NSExtensionContext : 공유된 데이터(URL, 이미지 등)에 접근하기 위한 컨텍스트로, ShareExtension과 함께 사용하는 핵심 클래스이다. 쉽게 말하면 확장과 호스트 앱 사이의 교류 통로 역할을 한다.

 

 NSExtensionContext는 현재 확장의 실행 환경을 나타낸다. ShareExtension에서는 사용자가 공유 버튼을 눌러 데이터를 보낼 때, 그 데이터가  NSExtensionContext에 담겨 전달된다. 이 객체를 통해 확장은 호스트 앱에서 전달한 데이터를 읽거나, 확장 실행 종료 후 결과를 전달할 수 있다.

 

 ShareExtension은 일반적으로 URL, 이미지, 텍스트 등을 공유할 때 호출된다. 이 데이터들은 NSExtensionContext의 inputItems 배열 안에 들어있다. 자세한 내용은 가이드 문서를 참고하면 좋을 것 같다. 

 

3. isContentValid() : 입력된 내용이 유효한지 검사하는 메소드 

 

4. didSelectPost() : 사용자가 "Post" 버튼을 눌렀을 때 실행되는 메소드

 

5. didSelectCancel() : 사용자가 "Cancel"을 눌렀을 때 실행되는 메소드

 

6. configurationItems() : 하단에 추가 옵션(카테고리 선택 등)을 넣을 때 사용하는 메소드

 

import Social
import UIKit

class ShareViewController: SLComposeServiceViewController {
  
  override func isContentValid() -> Bool {
    return !contentText.isEmpty
  }
  
  override func didSelectPost() {
    if let item = extensionContext?.inputItems.first as? NSExtensionItem {
      if let attachment = item.attachments?.first {
        attachment.loadItem(forTypeIdentifier: "public.url", options: nil) { data, error in
          if let url = data as? URL {
            print("공유된 URL: \(url)")
          }
        }
      }
    }
    
    self.extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
  }
  
  override func configurationItems() -> [Any]! {
    return []
  }
}

 간단한 코드를 작성해 봤다. 천천히 살펴보자. 일단 isContentValid() 메소드를 통해 내용이 비어있지 않을 때만 Post 가능하게 구현했다. 사용자가 입력한 텍스트는 contentText를 사용하면 간단하게 접근할 수 있다. didSelectPost() 메소드를 통해 URL을 가져오도록 했고, extensionContext의 completeRequest를 통해 URL을 정상적으로 가져왔으면 익스텐션을 종료하도록 했다.