본문 바로가기
IOS App Programming/IOS 연습

FCM 푸시알림 사용기3 - 푸시 알림 클릭 핸들링

by B_Tori 2024. 2. 21.

푸시 알림 기능의 기본적인 것들을 구현했으니 조금 더 나은 사용자 경험을 위해 푸시 알림을 클릭하면 관련 화면으로 이동할 수 있도록 구현하기로 하였다.

UNUserNotificationCenterDelegate

extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        NotificationService.shared.displayResetBadge()
        completionHandler([.list, .banner, .sound])
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        moveNotificationView()
        completionHandler()
    }
}
  • userNotificationCenter(_:willPresent:withCompletionHandler) : 앱이 실행 중일 때 알림이 도착하는 경우 실행되는 함수 앱 실행 시에도 알림 배너 등을 표시 -> completionHandler([. list,. banner,. sound])를 통해 구현
  • userNotificationCenter(_:didReceive:withCompletionHandler:) : 푸쉬알림을 클릭했을 때 실행되는 함수

 

푸시 클릭 시 화면 전환

1. 알림뷰로 이동

private func moveNotificationView() {
    if UIApplication.shared.connectedScenes.first?.delegate is SceneDelegate {
        guard let rootViewController = (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.window?.rootViewController else { return }
        let notificationViewController = NotificationViewController()
        if let tabBarController = rootViewController as? UITabBarController {
            if let selectedNavigationController = tabBarController.selectedViewController as? UINavigationController {
                selectedNavigationController.pushViewController(notificationViewController, animated: true)
            }
        } else if rootViewController is UINavigationController {
            rootViewController.navigationController?.pushViewController(notificationViewController, animated: true)
        }
    }
}

푸시 알림을 누르면 알림뷰로 이동하도록 설정하였다.

 

루트 뷰 컨트롤러가 탭 바일경우와 네비게이션 컨트롤러일 경우 두 가지 경우를 고려하여 이동할 수 있도록 하였다.

+ 탭 바일 경우 선택된 뷰 컨트롤러의 네비게이션을 타고 이동할 수 있도록 하였다.

 

이후 본 앱의 경우 루트뷰 컨트롤러가 무조건 탭바이기 때문에 네비게이션 뷰일 경우를 삭제하였다.

본인 앱 상황에 맞춰 알맞게 코드를 작성하면 될 것 같다.

 

2. 알림 타입에 따라 다른 뷰로 이동

메시지 알림의 경우 알림뷰 보다는 채팅뷰로 이동하는 것이 나을 것 같아

메시지 알림만 채팅뷰로 이동하도록 수정하는 업데이트를 거쳤다.

	 private func moveNotificationView() {
        if UIApplication.shared.connectedScenes.first?.delegate is SceneDelegate {
            guard let rootViewController = (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.window?.rootViewController else { return }
            let notificationViewController = NotificationViewController()
            if let tabBarController = rootViewController as? UITabBarController {
                if let selectedNavigationController = tabBarController.selectedViewController as? UINavigationController {
                    selectedNavigationController.pushViewController(notificationViewController, animated: true)
                }
            } else if rootViewController is UINavigationController {
                rootViewController.navigationController?.pushViewController(notificationViewController, animated: true)
            }
        }
    }
    
    private func moveChattingView() {
        if UIApplication.shared.connectedScenes.first?.delegate is SceneDelegate {
            guard let rootViewController = (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.window?.rootViewController else { return }
            if let tabBarController = rootViewController as? UITabBarController {
                tabBarController.selectedIndex = 1
                if let navigationController = tabBarController.viewControllers?[1] as? UINavigationController {
                    navigationController.popToRootViewController(animated: true)
                }
            }
        }
    }

알림 타입을 어떻게 구분은 알림의 Subtitle 유무로 구분하기로 했다.

메시지의 경우에만 subtitle이 있기 때문에 가능했다.

페이로드에 구분 정보를 포함시켜 보내는 방법이 있지만 기존 코드를 많이 수정하고 싶지 않아 이러한 방법을 사용하였다.

 

우선 알림뷰로 이동하는 함수와 채팅뷰로 이동하는 함수 두가지를 작성한 뒤 서브타이틀 유무에 따라 다른 함수를 호출하였다.

처음에 적었던 userNotificationCenter(_:didReceive:withCompletionHandler:) 함수에 작성하면 된다.

댓글