최근 애플리케이션에서 "알림"이라는 기능이 없는 앱.. 혹시 보셨나요?
전 못본 것 같아요
아주 간단한 투두 어플도 푸시 알림을 보내주더군요...
iOS 환경에서 개발자는 두가지 종류의 알림을 보내줄 수 있어요
서버에서 원격으로 알림을 생성하여 APNs(Apple 푸시 알림 서비스)가 기기에 전달해주는 방법,
로컬에서 알림 콘텐츠를 생성하고 트리거(조건)에 맞게 알림을 띄워주는 방법이 있습니다
사실 이런 알람을 설정하기 전, 반드시 해야하는 작업이 있죠?
네...
사용자 기기에 알림을 보낼 수 있게 권한 허용받기
이게 설정되지 않으면 어떤 방식도 쓸 수 없어요!!!!!
요거 허용받는 설정과 관련된 부분을 간단히 적어볼게요
🩵 NotificationCenter
NotificationCenter 하면 어떤게 떠오르시나요?
사용자에게 푸시 알림을 보내주는 것?
일단 "알림"에 관련된 건 맞습니다ㅎㅎ
NotificationCenter는
사용자에게 뭔가를 알려주는 역할이라기 보다,
애플리케이션 안에서 정보를 전달하는 알림을 보내주는 역할에 가까워요
공식문서에는 이렇게 작성되어 있습니다
A notification dispatch mechanism that enables the broadcast of information to registered observers.
등록된 관찰자에게 정보를 브로드캐스팅할 수 있는 알림 발송 메커니즘입니다
풀어서 말해볼까요?
NotificationCenter는 애플리케이션에서 특정한 이벤트가 발생했을 때
이벤트가 발생했다는 사실을
관심을 갖고 있던(해당 이벤트에 반응하도록 설계된) 객체나 컴포넌트에게 자동으로 알려주는 시스템입니다
이런건 간단히 Observer 패턴이라고도 하죠
객체 간 결합도를 낮추면서 효율적인 상태 변경을 할 수 있게 도와줘요
앱의 각기 다른 부분이 독립적으로 유지되면서 특정 이벤트에 반응할 수 있게 하는 것이죠!!
예를 들어, 중요한 데이터가 업데이트 됐을 때 여러 UI 컴포넌트가 이것을 감지하고 업데이트를 준비하는 것 처럼 말이에요
(사실 이런 부분에서는 Delegate 패턴을 더 많이 써요 🥹)
✔️ 구성 요소
Notifications
- 발생하는 이벤트를 의미합니다
- NSNotification 객체로 표현되어요
- 이 객체는 이벤트에 대한 정보를 담고 있습니다
NotificationCenter
- 모든 알림이 NotificationCenter의 인스턴스를 통해 관리됩니다
- 모든 앱은 default NotificationCenter 인스턴스를 가지고 있어요
✔️ 사용 방법
알림 수신자 등록하기
- 특정 이벤트에 반응하고 싶은 객체는 자기 자신을 알림 수신자로 등록해야 합니다
addObserver(_:selector:name:object:)
알림 발송하기
- 특정 이벤트가 발생했을 때, 관련된 알림을 발송할 수 있어요
post(name:object:userInfo:)
알림 수신자 제거하기
- 더 이상 변경등의 알림을 받고 싶지 않은 객체라면 NotificationCenter에서 자기 자신을 제거하면 돼요
removeObserver(_:)
🩵 AppDelegate 설정
사용자에게 권한 요청을 하기 위해서는 UserNotifications를 사용해야 합니다
하지만! 절대로 인스턴스를 직접 생성하면 안됩니다
current()라는 메서드를 통해 앱의 NotificationCenter를 반환해주어야 해요
https://developer.apple.com/documentation/usernotifications/unusernotificationcenter/current()
import UserNotifications
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_:didFinishLaunchingWithOptions:) // 여기에 작성
}
- UNAuthorizationOptions : badge, sound, alert
- requestAutorization(options:completionHandler:) 메서드
이 2개의 요소를 사용해서 기본 옵션을 설정해줍니다
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let authOptions: UNAuthorizationOptions = [.alert, .sound, .badge]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { res, error in
if res {
print("사용자가 알림을 허용했습니다.")
} else {
print("사용자가 알림을 거부했습니다.")
}
}
return true
}
대충 테스트해보면 이런식으로 정상 작동!
🩵 원격 알림 / 로컬 알림 차이점
푸시 알림 기능을 사용하기 위해서 위에 적힌 정도까지만 해 주면 로컬 알림은 사용할 수 있어요
하지만! 원격 알림을 사용하려면 추가적인 작업이 필요합니다
- APNs에 디바이스 등록하기
- 디바이스 토큰 받아오기
이 토근은 서버가 특정한 사용자에게 알림을 보낼 때 사용됩니다!
import UIKit
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// 알림 권한 요청
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { res, error in
if res {
DispatchQueue.main.async {
application.registerForRemoteNotifications()
}
}
}
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// 디바이스 토큰을 받음
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
print("Device Token: \(token)")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
// 디바이스 토큰 등록 실패
print("Failed to register: \(error)")
}
}
기초중의 기초!
권한 요청하기에 대해 공부해봤어요
조금 더 세세한 트리거를 다루는 방법도 공부중입니다
현재로서는 APNs는 사용할 일이 없어서,,, 로컬 알림쪽으로만ㅎㅎ
~ヾ(^∇^)
https://developer.apple.com/documentation/usernotifications
https://developer.apple.com/documentation/foundation/notificationcenter
'iOS > Swift' 카테고리의 다른 글
[Swift]Unit Test (1) 코드 테스트의 원칙 (0) | 2024.03.06 |
---|---|
[Swift] 열거형 Enumeration / 타입 안정성 (0) | 2024.03.04 |
[Swift] CollectionView 동적으로 Cell 크기 계산하기 (2) | 2024.03.01 |
[Swift] 프레임워크와 라이브러리 (3) 접근제한자 (0) | 2024.02.29 |
[Swift] 프레임워크와 라이브러리 (2) UIKit SnapKit으로 비교하기 (0) | 2024.02.27 |