iOS) Widget 으로 앱 접근 시 화면 이동
내용
- 특정 widget 에서 앱으로 접근 시를 구분하여 분기 처리를 대응해보자.
- 위젯의
widgetURL()
로부터 넘겨준 URL 의 쿼리를 매개변수로 사용해보자.
우선, widget 으로 앱에 접근할 때의 상황은 크게 두 가지로 나뉩니다.
- 앱을 실행시켜서 foreground 로 진입
- background 에서 foreground 로 진입
이 상황들에 대응하기 위해서 다음의 메서드를 SceneDelegate 에서 사용할 수 있습니다.
scene(_:willConnectTo:options:)
- delegate(UISceneDelegate) 에게 앱에 scene 추가에 대해서 알립니다.
// scene: app 에 연결되는 scene 객체.
// session: scene configuration 에 대한 세부 정보가 포함된 session 객체.
// connectionOptions: scene 을 구성하기 위한 추가 옵션. 이 객체의 정보를 사용하여 scene 생성을 일으킨 작업을 처리. 예를 들어, 사용자가 선택한 quick action 에 응답.
optional func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
)
scene(_:openURLContexts:)
- delegate(UISceneDelegate) 에게 하나 이상의 URL을 열도록 요청합니다.
// scene: UIKit 이 URL 을 열라고 요청하는 scene
// URLContexts: 하나 이상의 UIOpenURLContext 객체. 각 객체는 하나의 URL 과 URL 을 열기 위한 추가적인 정보를 포함.
optional func scene(
_ scene: UIScene,
openURLContexts URLContexts: Set<UIOpenURLContext>
)
위젯을 열때 다음과 같이 URL 이 전달됩니다.
struct MyCardEntryView: View {
Image("widget")
// ✅ cardUUID 값을 쿼리형태로 URL 에 추가.
.widgetURL(URL(string: "openMyCardWidget://?cardUUID=\(cardUUID)"))
}
1️⃣ 앱을 실행시켜서 foreground 로 진입
scene(_:willConnectTo:options:)
메서드를 사용- 앱에 scene 을 추가할 때 즉, 앱을 런치할 때에 해당 메서드로 delegate 에게 알림니다.
// SceneDelegate.swift
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
private let myCardURL = "openMyCardWidget"
private let qrCodeURL = "openQRCodeWidget"
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// urlContexts : 열기 위한 meatadata 및 URL.
if let url = connectionOptions.urlContexts.first?.url {
// ✅ 전달된 url 을 통해서 분기처리.
if url.absoluteString == qrCURL {
// ✅ 화면 이동에 필요한 UserDefaults 추가.
UserDefaults.standard.setValue(true, forKey: Const.UserDefaultsKey.openQRCodeWidget)
}
// ✅ "openMyCardWidget://?cardUUID=123456" 과 같이 전달.
else if url.absoluteString.starts(with: myCardURL) {
// ✅ queryItems 에서 "cardUUID" 값 사용.
guard let queryItems = URLComponents(string: url.absoluteString)?.queryItems,
let cardUUID = queryItems.filter({ $0.name == "cardUUID" }).first?.value else { return }
UserDefaults.standard.setValue(cardUUID, forKey: Const.UserDefaultsKey.widgetCardUUID)
}
}
}
}
2️⃣ background 에서 foreground 로 진입
scene(_:openURLContexts:)
메서드를 사용- URL 을 여는 요청에서 URL 을 확인 후에 특정 화면으로 이동.
- 즉, 앱을 런치하지 않을 때 URL 을 다루기 위해 사용할 수 있습니다.
// SceneDelegate.swift
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url,
let urlComponents = URLComponents(string: url.absoluteString) else { return }
if qrCodeURL == url.absoluteString {
// qr code 위젯.
}
} else if url.absoluteString.starts(with: myCardURL) {
// 내 명함 위젯.
}
}
}
👉 참고
카메라로 QR 코드를 찍어서 동적링크로 앱을 실행하는 경우에는 다른 delegate 메서드를 사용하기 때문에 알아보겠습니다.
scene(_:continue:)
- delegate 에게 지정된 Handoff-related activity 를 처리하도록 알립니다.
// ✅ user acticty 와 관련된 데이터를 scene 에서 사용하여 작업을 이어갈 수 있다.
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if let url = userActivity.webpageURL {
// ...
}
}
출처: