기어가더라도 제대로

AppDelegate, SceneDelegate, VC 에 접근하기 본문

UIKit 기초

AppDelegate, SceneDelegate, VC 에 접근하기

Damagucci-juice 2022. 8. 23. 10:33

목차

1. AppDelegate 
    1. → VC
    2. → SceneDelegate
2. SceneDeleagate
    1. → AppDelegate
    2. → VC
3. VC
    1. → AppDelegate
    2. → SceneDelegate

정의

앱의 구성요소들 간에 참조가 필요할 때가 있다. 앱의 생명 주기에 관한 일이라든지 ..

하다가 적어 놓으면 나중에 잊어버렸을 때 유용할 거 같아서 정리를 해놓는다.

사용법

AppDelegate → VC

마땅한 방법이 없다. 왜 그러냐면은 AppDelegate 에 window 가 있던 시절엔 가능했지만,
이젠 기본적으로 SceneDelegate 로 window 가 옮겨갔다.

그나마 이 경우엔 두가지가 있다.

  1. 1. VC 에서 접근하고자 하는 속성이나 메서드를 싱글톤으로 선언을 해놓는 것이다.

그렇게 되면 VC.someproperty 처럼 접근이 가능하다.

class FirstViewController: UIViewController {
    static func printFive() {
    	(1...5).forEach { num in
            print(num)
        }
    }
}
  1. 2.AppDelegate에서 스토리 보드를 초기화 시키고 스토리 보드의 초기화
    1. 스토리 보드의 아이디로 스토리 보드를 변수화
    2. 그 스토리보드의 루트 뷰컨을 우리가 사용하고자 하는 뷰컨으로 사용

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        guard let firstVC = storyboard.instantiateViewController(withIdentifier: "FirstViewController")
                as? FirstViewController else { return true }
        firstVC.printFive()

        return true
    }
}

class FristViewController: UIViewContorller {
        func printFive() {
        (1...5).forEach { num in
            print(num)
        }
    }
}

AppDelegate → SceneDelegate

굳이 접근할 필요가 있나 싶긴한데.. 혹시 몰라서 찾아보긴 했으나, 정말 적은 코드가 있다.

이걸 접근이라 부르긴 좀 어렵다. AppDelegate에서 SceneConfiguraton 을 주입하는 것인데, 아직 언제 사용할 지는 모르겠다.

// AppDelegate
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {

        let configuration = UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
        if connectingSceneSession.role == .windowApplication {
            configuration.delegateClass = SceneDelegate.self
        }

        return configuration
    }

//SceneDelegate
class SceneDelegate: NSObject, ObservableObject, UIWindowSceneDelegate {
    var window: UIWindow?   // << contract of `UIWindowSceneDelegate`

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = scene as? UIWindowScene else { return }
        self.window = windowScene.keyWindow   // << store !!!
    }
}

요약하자면 앱 델리게이트에서 신델리게이트에 대한 설정을 주입하고, 그 설정을 바탕으로 신델리게이트를 앱이 생성한다.

SceneDelegate → AppDelegate

간단하다.

guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }

SceneDelegate → VC

역시 간단하다.

guard let vc = window?.rootViewController as? UIViewController else { return }

VC → AppDelegate

이제 식은 죽먹기다

guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
appDelegate.printWhoAmI()

VC → SceneDelegate

여기가 좀 방식이 다양한데, 어느 것이 가장 좋은 방식인지는 모르겠다.

  • SceneDelegate 에서 자기 자신을 싱글톤으로 속성을 만드는 방법
class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?
    static var shared: SceneDelegate?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let _ = (scene as? UIWindowScene) else { return }

        Self.shared = self
    }
}
  • 연결된 scene을 찾고 가져오는 방법 1
if #available(iOS 13.0, *) {
            for scene in UIApplication.shared.connectedScenes {
                let window = UIWindow(windowScene: scene as! UIWindowScene)
                let sceneDelegate = window.windowScene?.delegate as! SceneDelegate
                sceneDelegate.printWhoAmI()
            }
        } else {

        }
  • UIApplication에서 연결된 Scene을 찾고 SceneDelegate를 가져오는 방법 2
//VC's ViewDidLoad() ..

guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
        let sceneDelegate = windowScene.delegate as? SceneDelegate
else {
      return
}

출처

Is it possible to run a View Contr... | Apple Developer Forums

How to access own window within SwiftUI view?

[iOS - SceneDelegate] iOS13이상 버전의 SceneDelegate

Comments