알림 설정 상태를 실시간으로 가져와 UI에 반영시키는 with RxSwift

15189 단어 iOSSwiftRxSwiftRxCocoa

개요


  • 화면의 변경을 별로 의식하지 않고, 통지 설정을 취득·UI에 반영하는 방법을 쓴다
  • 앱 개발을 하고 있을 때, 통지 설정 화면에서 통지 설정 상태를 취득해, 通知設定がOFFになっています 같은 화면을 구현하는 것, 자주 있는 것이 아닐까요? 이번은 그 구현을 RxSwift를 이용해 만들고 싶습니다

  • 이미지




  • 화면을 열 때마다 알림 설정을 얻고 UI 업데이트

  • 샘플 리포지토리


  • htps : // 기주 b. 코 m / 료 타카 하시 / R

  • 환경


  • Xcode9.4
  • Swift4.1
  • RxSwift4.2
  • RxCocoa4.2

  • 소개


    pod install 'RxSwift'
    pod install 'RxCocoa'
    

    화면 만들기




    ViewController
    DisableNotificationCoverView





    DisableNotificationCoverView를 맨 위 계층에 배치하고 isHidden = true로 둡니다.
    일단 사용할 수 있도록 View를 잘라냅니다.


    통지 상태를 좋은 느낌으로 취득해 주는 클래스의 작성



    RxNotificationCenter.swift
    import RxSwift
    import RxCocoa
    import UserNotifications
    
    class RxNotificationCenter {
        static let shared = RxNotificationCenter()
    
        let authorizationStatus = PublishRelay<UNAuthorizationStatus>()
    
        private init() {}
    
        func updateAuthorizationStatus() {
            // 通知設定状態を取得し、オブザーバに流す
            UNUserNotificationCenter.current().getNotificationSettings { [weak self] settings in
                self?.authorizationStatus.accept(settings.authorizationStatus)
            }
        }
    }
    
  • 싱글 톤 인스턴스로 사용할 수 있도록 정의

  • 알림 꺼져요 표지보기 만들기



    DisableNotificationCoverView.swift
    class DisableNotificationCoverView: UIView {
    
        @IBOutlet weak var openNotificationSettingButton: UIButton!
    
        private let disposeBag = DisposeBag()
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            commonInit()
        }
    
        override func awakeFromNib() {
            openNotificationSettingButton.rx.tap
                .subscribe(onNext: { [weak self] in
                    // ボタンがタップするたびにここの処理が呼ばれる
                    if let url = URL(string: UIApplicationOpenSettingsURLString), UIApplication.shared.canOpenURL(url) {
                        // 本体設定のこのアプリの設定画面を開く処理
                        UIApplication.shared.open(url, options: [:], completionHandler: nil)
                    }
                })
                .disposed(by: disposeBag)
        }
    
        private func commonInit() {
            let bundle = Bundle(for: type(of: self))
            let nib = UINib.init(nibName: "DisableNotificationCoverView", bundle: bundle)
            let view = nib.instantiate(withOwner: self, options: nil).first as! UIView
            self.addSubview(view)
        }
    }
    
    
  • 통지를 취득하는 처리와 통지 설정으로 이동시키는 화면이 생겼으므로 여기에서 통지 설정 화면 (임시)을 만들어 간다

  • 알림 설정 화면


  • 여기서 할 일은 다음과 같습니다.
  • 처음 화면을 만들 때
  • RxNotificationCenter 알림 설정 상태의 관찰자를 모니터링하고 변경이 있으면 UI 변경
  • 통지 설정 상태를 취득해 옵저버에 흘리도록 명령

  • 화면을 다시 표시했을 때 (한 번 떨어져 다른 화면에서 다시 전환했을 때 등)
  • 통지 설정 상태를 취득해 옵저버에 흘리도록 명령



  • ViewController.swift
    import UIKit
    import UserNotifications
    import RxSwift
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var disableNotificationCoverView: UIView!
    
        private let disposeBag = DisposeBag()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            navigationItem.title = "通知設定"
            setupViewController()
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            // 通知設定状態を取得させてオブザーバに流すように命令
            RxNotificationCenter.shared.updateAuthorizationStatus()
        }
    
        private func setupViewController() {
            // RxNotificationCenterの通知設定状態のオブザーバを監視、変更があったらUIを変更する
            RxNotificationCenter.shared.authorizationStatus
                .map { status -> Bool in
                    switch status {
                    case .authorized:
                        return true
                    case .denied, .notDetermined:
                        return false
                    }
                }
                .bind(to: disableNotificationCoverView.rx.isHidden)
                .disposed(by: disposeBag)
            // 通知設定状態を取得させてオブザーバに流すように命令
            RxNotificationCenter.shared.updateAuthorizationStatus()
        }
    }
    

    마지막으로 알림 설정 화면에서 앱으로 돌아올 때 알림 설정 상태를 얻습니다.



    AppDelegate.swift
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        func applicationWillEnterForeground(_ application: UIApplication) {
            RxNotificationCenter.shared.updateAuthorizationStatus()
        }
    
    }
    
  • 홈 화면이나, 다른 앱으로부터 돌아왔을 때, ViewControllerviewWillAppear , viewDidAppear 가 불리는 것이 아닐까 생각하기 쉽지만, 실은 불리지 않습니다.
  • AppDelegateapplicationWillEnterForeground가 불리기 때문에, 거기에 통지 취득 처리를 사이에 둔다

  • 요약


  • RxSwift/RxCocoa를 사용하여 통지 상태를 View bind함으로써 거기까지 UI의 변화를 의식하지 않고 통지 설정 취득 처리를 작성할 수 있었다
  • 홈 화면, 다른 앱에서 앱으로 돌아왔을 때는 AppDelegate の applicationWillEnterForeground`

  • Notes


  • 이렇게 쓰면 더 스마트해질거야, 의 목소리, 기다리고 있습니다 🙏
  • 좋은 웹페이지 즐겨찾기