혹시 공유하기 기능을 알고 계신가요?
당연히 알고 계시겠죠 히히
그렇다면 공유하기 할 때 앱 마다 작은 앱이 나오는 원리라는것을 알고 계셨나요?
저도 이번 출시앱을 개발하다 보니 알게 되서 공유해보고자 합니다.
이번 시간에는Share Extension
에 대해서 배워 보도록 하겠습니다!
사용자가 앱과 콘텐츠를 공유할 수 있도록 하는 확장(Extension)앱 입니다.
이를 통해 사용자는 다른 앱에서 텍스트, 이미지, URL 등 다양한 형태의 데이터를 가져와서
자신의 앱으로 공유할 수 있습니다.
위 사진과 같이
Share Extention
를 추가하시고
App Group 을 생성하시고 활성화 해주세요
주의 하실 부분은 main App 의 App Group 도 활성화 해주셔야 합니다!
NSExtensionActivationSupportsWebURLWithMaxCount
= 확장에서 지원할 최대 URL 수를 지정
위와 같이 ShareExtention infoplist 를 활성화 해주세요
import Social
import Combine
import UniformTypeIdentifiers
final class ShareViewController: UIViewController {
private var viewModel = SharedViewModel()
override func viewDidLoad() {
super.viewDidLoad()
setting()
handleSharedURL()
}
private func setting() {
... UI 구성 관련
}
private func setLayout(viewCon: UIViewController) {
... Layout 관련
}
private func handleSharedURL() {
// 공유된 항목 가져오기
if let item = extensionContext?.inputItems.first as? NSExtensionItem {
if let attachments = item.attachments {
for provider in attachments {
// URL을 처리하기 위한 타입 확인
if provider.hasItemConformingToTypeIdentifier(UTType.url.identifier) {
provider.loadItem(forTypeIdentifier: UTType.url.identifier, options: nil) { (item, error) in
if let url = item as? URL {
// YouTube URL 확인 및 처리
self.processYouTubeURL(url)
}
}
} else if provider.hasItemConformingToTypeIdentifier(UTType.text.identifier) {
provider.loadItem(forTypeIdentifier: UTType.text.identifier, options: nil) { (item, error) in
if let url = item as? String {
// YouTube URL 확인 및 처리
self.processYouTubeURL(url)
}
}
}
}
}
}
}
private func processYouTubeURL(_ url: URL) {
// 앱 그룹을 통해 메인 앱에 전달
if let userDefaults = UserDefaults(suiteName: "group.guideu.youtube"),
let encode = encoding(string: url.absoluteString) {
userDefaults.setValue(encode, forKey: "sharedURL")
print("공유받은 YouTube URL: \(url.absoluteString)")
userDefaults.synchronize()
DispatchQueue.main.async { [weak self] in
self?.viewModel.trigger = true
}
} else {
close()
}
}
private func processYouTubeURL(_ string: String) {
// 앱 그룹을 통해 메인 앱에 전달
if let userDefaults = UserDefaults(suiteName: "group.guideu.youtube"),
let encode = encoding(string: string) {
userDefaults.setValue(encode, forKey: "sharedURL")
print("공유받은 YouTube URL: \(string)")
userDefaults.synchronize()
DispatchQueue.main.async { [weak self] in
self?.viewModel.trigger = true
}
} else {
close()
}
}
private func encoding(string: String) -> Data? {
return try? JSONEncoder().encode(string)
}
private func close() {
// Share Extension 종료 및 앱 이동
self.extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
}
private func openMainApp() {
let urlScheme = "guideu://"
if let url = URL(string: urlScheme) {
// 앱 실행
if self.openURL(url) {
print( "RUN : APP")
} else {
print( "NOT RUN : APP")
}
close()
}
}
@objc private func openURL(_ url: URL) -> Bool {
var responder: UIResponder? = self
while responder != nil {
if let application = responder as? UIApplication {
return application.perform(#selector(openURL(_:)), with: url) != nil
}
responder = responder?.next
}
return false
}
}
final class SharedViewModel: ObservableObject {
@Published var trigger = false
}
위와 같이 간단하게 구성해 보았는데요!
약간 생소하신 코드가 하나가 보일것입니다.@objc private func openURL(_ url: URL) -> Bool { var responder: UIResponder? = self while responder != nil { if let application = responder as? UIApplication { return application.perform(#selector(openURL(_:)), with: url) != nil } responder = responder?.next } return false }
약간 의문이 들었을수도 있다고 생각이 듭니다.
다만, Share Extention 에선UIApplication.shared.open(<#T##url: URL##URL#>)
를 사용할 수가 없습니다
위와 같은 방법을 통해서도 open URL을 실행 시킬수 있습니다!
출시후 공개 예정