• Jan
  • Feb
  • Mar
  • Apr
  • May
  • Jun
  • Jul
  • Aug
  • Sep
  • Oct
  • Nov
  • Dec
  • Sun
  • Mon
  • Tue
  • Wed
  • Thu
  • Fri
  • Sat
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Onboarding screen iOS 13 이상에서 적용

엑코 버전 11에서는 프로젝트를 만들면 AppDelegate 뿐만 아니라
SceneDelegate 파일도 생성된다.

iOS 13 이상에서는, UserDefaults.standard.bool(forKey:"어쩌구") 사용해서
유저가 앱을 처음 Launch 하는지 아닌지에 따라 Onboarding 스크린을 띄우는 작업을
SceneDelegate에서 해야 한다. 13 이상에서 UI Lifecycle은 SceneDelegate에서 !

당연히 iOS 13 미만에서는 그대로 AppDelegate에 따라 동작하기 때문에,
해당 OS 버전 기기를 고려하기 위해서는 AppDelegate도 동일 코드가 존재해야 한다.

근데 알아서 OS따라 맞는거 찾아서 실행하겠지~하고
다짜고짜 AppDelegate랑 SceneDelegate에 같은 코드 때려넣으면 안 됨.
iOS 13 이상에서도 Process LifeCycle 등 다른 목적으로 AppDelegate를 쓰긴 쓰기 때문에…

그리고 게다가 실행 순서가
AppDelegate → SceneDelegate!

즉, AppDelegate가 먼저 실행되고 그 다음 SceneDelegate가 실행됨
그래서 AppDelegate랑 SceneDelegate에 같은 코드를 복붙해놓으면
AppDelegate에 있는 코드가 먼저 실행돼서 Onboarding Screen이 안 뜨고
바로 main으로 넘어가게 된다.

이미 AppDelegate의 코드 때문에 UserDefaults의 값은 변경되어서,
SceneDelegate의 분기문 안으로는 들어가지 않기 때문에 마찬가리고 Onboarding Screen은 볼 수 없다.

그래서 AppDelegate에는 OS 버전에 따른 분기를 추가 해 줘야 한다.

// AppDelegate.swift - didFinishLaunchingWithOptions 함수

if #available(iOS 13, *) {
print("SceneDelegate에서 처리")

) } else { 

        let launchedBefore = UserDefaults.standard.bool(forKey: "hasLaunched")
        let launchStoryboard = UIStoryboard(name: "Onboarding", bundle: nil)
        let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
        var vc: UIViewController
        if launchedBefore
        {
            vc = mainStoryboard.instantiateInitialViewController()!
        }
        else
        {
            vc = launchStoryboard.instantiateViewController(identifier: "OnboardingViewController")
        }
        UserDefaults.standard.set(true, forKey: "hasLaunched")
        self.window?.rootViewController = vc
        
        guard let _ = (scene as? UIWindowScene) else { return }

}

요런 식으로!

// SceneDelegate.swift - willConnectTo 함수

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        
        let launchedBefore = UserDefaults.standard.bool(forKey: "hasLaunched")
        let launchStoryboard = UIStoryboard(name: "Onboarding", bundle: nil)
        let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
        var vc: UIViewController
        if launchedBefore
        {
            vc = mainStoryboard.instantiateInitialViewController()!
        }
        else
        {
            vc = launchStoryboard.instantiateViewController(identifier: "OnboardingViewController")
        }
        UserDefaults.standard.set(true, forKey: "hasLaunched")
        self.window?.rootViewController = vc
        
        guard let _ = (scene as? UIWindowScene) else { return }

    }