Library

UIKitPlus - RootViewController

GREEN.1229 2021. 6. 23. 12:40

안녕하세요. 그린입니다🟢

이번 포스팅에서는 UIKitPlus에서 RootViewController에 대해 학습해보겠습니다🧑🏻‍💻

 

RootViewController?

루트 네비게이션 뷰 컨트롤러의 호출과 사용법에 대해 어떻게 구성되는지 단계별로 알아보겠습니다.

 

1. RootViewController 파일 생성 및 정의

 - RootViewController.swift 파일을 생성하고 RootController<DeeplinkType>을 아래와 같이 상속하여 필요 기능을 정의

import UIKitPlus

class RootViewController: SwifRootViewController<DeeplinkType> {
    // 앱 시작시 초기 뷰 컨트롤러 표시
    override var splashScreen: UIViewController {
        SplashViewController() // 정의 가능
    }
    // showLoginScreen에서 사용자가 이동할 위치
    override var loginScreen: UIViewController {
        LoginViewController() // 정의 가능
    }
    // switchToLogout에서 사용자가 이동할 위치
    override var logoutScreen: UIViewController {
        LoginViewController() // 정의 가능
    }
    // 인증된 사용자에게 보여줄 메인 뷰 컨트롤러
    override var mainScreen: UIViewController {
        MainViewController() // 정의 가능
    }
    // 메인 뷰 앞에 표시
    override var onboardingScreen: UIViewController? {
        // 반환하여 승인 직후 표시
        nil
    }
    // 승인 확인 후 적절한 화면 반환
    override var initialScreen: UIViewController {
        Session.shared.isAuthorized ? splashScreen : loginScreen
    }
    // 딥링크 처리
    override func handleDeepLink(type: DeeplinkType) {
        /// 딥링크를 다룰 스위치/케이스 조건에 따라 딥 링크 확인
        /// 맞는 뷰 컨트롤러로 이동 구현
    }
}

2. window의 RootController 세팅 (AppDelegate)

@UIApplicationMain
class AppDelegateBase: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        if #available(iOS 13.0, *) {
            // use scene delegate
        } else {
            window = UIWindow(frame: UIScreen.main.bounds)
            RootViewController().attach(to: window)
        }
        ShortcutParser.shared.registerShortcuts()
        return true
    }
}

3. SceneDelegate 설정

@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

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

4. 화면전환

 - UIView, UIViewController, UIApplicationDelegate에서 설정한 RootViewController를 호출할 수 있음

rootController.switch(to: .login, animation: .none)
rootController.switch(to: .main, animation: .fade)
rootController.switch(to: .logout, animation: .dismiss)

Deep Link 설정

import Foundation
import UIKit

enum ShortcutKey: String {
    case activity = "com.yourapp.activity"
    case messages = "com.yourapp.messages"
}

class ShortcutParser {
    static let shared = ShortcutParser()
    private init() { }

    func registerShortcuts() {
        let activityIcon = UIApplicationShortcutIcon(type: .invitation)
        let activityShortcutItem = UIApplicationShortcutItem(type: ShortcutKey.activity.rawValue, localizedTitle: "Recent Activity", localizedSubtitle: nil, icon: activityIcon, userInfo: nil)

        let messageIcon = UIApplicationShortcutIcon(type: .message)
        let messageShortcutItem = UIApplicationShortcutItem(type: ShortcutKey.messages.rawValue, localizedTitle: "Messages", localizedSubtitle: nil, icon: messageIcon, userInfo: nil)

        UIApplication.shared.shortcutItems = [activityShortcutItem, messageShortcutItem]
    }

    func handleShortcut(_ shortcut: UIApplicationShortcutItem) -> DeeplinkType? {
        switch shortcut.type {
        case ShortcutKey.activity.rawValue:
            return  .activity
        case ShortcutKey.messages.rawValue:
            return  .messages
        default:
            return nil
        }
    }
}

Deep Link Manager 설정

import UIKitPlus

// 딥링크 열거 타입 설정
enum DeeplinkType {
    case messages
    case activity
}

let Deeplinker = DeepLinkManager()
class DeepLinkManager {
    fileprivate init() {}

    private var deeplinkType: DeeplinkType?

    @discardableResult
    func handleShortcut(item: UIApplicationShortcutItem) -> Bool {
        deeplinkType = ShortcutParser.shared.handleShortcut(item)
        return deeplinkType != nil
    }

    // 기존 딥링크를 확인 후 작업 수행
    func checkDeepLink() {
        if let rootViewController = AppDelegate.shared.rootViewController as? RootViewController {
            rootViewController.deeplink = deeplinkType
        }

        // 작업 처리 후 딥링크 재설정
        self.deeplinkType = nil
    }
}

AppDelegate 및 위와 같은 SceneDelegate 설정

@UIApplicationMain
class AppDelegateBase: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        if #available(iOS 13.0, *) {
            // SceneDelegate 사용
        } else {
            window = UIWindow(frame: UIScreen.main.bounds)
            RootViewController().attach(to: window)
        }
        ShortcutParser.shared.registerShortcuts()
        return true
    }
    func applicationDidBecomeActive(_ application: UIApplication) {
        super.applicationDidBecomeActive(application)
        Deeplinker.checkDeepLink()
    }
    
    // MARK: Shortcuts
    func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
        completionHandler(Deeplinker.handleShortcut(item: shortcutItem))
    }

    // MARK: UISceneSession Lifecycle
    @available(iOS 13.0, *)
    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    @available(iOS 13.0, *)
    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {}
}

 

[참고자료]

https://github.com/MihaelIsaev/UIKitPlus

https://github.com/MihaelIsaev/UIKitPlus/blob/master/Docs/RootViewController.md