BDD(Behavior-driven development)

1 minute read

// AppDelegate.swift

// ...

// ✅ 메시지 수신
extension AppDelegate: UNUserNotificationCenterDelegate {

    // ...
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        // ✅ notification 의 payload 속 `recordId` 와 `roomId` 를 가지고 화면전화에서 사용할 수 있습니다.
        let userInfo = response.notification.request.content.userInfo
        guard let recordId: String = userInfo["recordId"] as? String,
              let roomId: String = userInfo["roomId"] as? String else { return }
        let info: [String: Any] = ["recordID": recordId, "roomID": roomId]

        // ✅ 포그라운드 상태만.(백그라운드는 제외할 수 있음)
        // (백그라운드에서는 SplashVC 를 거쳐서 이동하기 때문에 화면전환 코드를 분리해둠.)
        // UIApplication.shared.applicationState 를 사용하여 분기처리를 할 수 있다.
        let applicationState = UIApplication.shared.applicationState
        if applicationState == .active || applicationState == .inactive {

            // ✅ 푸시알림으로 앱을 실행하게 되면 메인 탭바가 등장하도록 설정.
            guard let mainTBC = UIStoryboard(name: Const.Storyboard.Name.mainTabBar, bundle: nil).instantiateViewController(withIdentifier: Const.ViewController.Identifier.mainTabBar) as? MainTBC else { return }
            
            // ✅ 메인 탭바로 rootViewController 를 변경.
            guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return }
            guard let window = windowScene.windows.first  else { return }
            window.rootViewController = mainTBC
            UIView.transition(with: window, duration: 0.5, options: .transitionCrossDissolve, animations: nil)
            
            // ✅ 0.5초 뒤에 habitRoomVC 로 push 하도록 설정.
                guard let habitRoomVC = UIStoryboard(name: Const.Storyboard.Name.habitRoom, bundle: nil).instantiateViewController(withIdentifier: Const.ViewController.Identifier.habitRoom) as? HabitRoomVC else { return }
                habitRoomVC.roomID = Int(roomId)
                
                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5) {
                    // 가장 위에 있는 view controller 를 가져오는 작업.
                    let toVC = UIApplication.getMostTopViewController()
                    topVC?.navigationController?.pushViewController(habitRoomVC, animated: true)
                
        }        

        completionHandler()
    }

    // ... 

}
  • getMostTopViewController()
// UIApplication+Extension.swift

import UIKit

extension UIApplication {
    public class func getMostTopViewController(of base: UIViewController? = nil) -> UIViewController? {
        var baseVC: UIViewController?
        
        if base != nil {
            baseVC = base
        } else {
            baseVC = (UIApplication.shared.connectedScenes
                .compactMap { $0 as? UIWindowScene }
                .flatMap { $0.windows }
                .first { $0.isKeyWindow })?.rootViewController
        }
        
        if let naviController = baseVC as? UINavigationController {
            return getMostTopViewController(of: naviController.visibleViewController)
        } else if let tabbarController = baseVC as? UITabBarController,
                  let selected = tabbarController.selectedViewController {
            return getMostTopViewController(of: selected)
        } else if let presented = baseVC?.presentedViewController {
            return getMostTopViewController(of: presented)
        }
        
        return baseVC
    }
}

Categories:

Updated: