1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Combineでkeyboard通知を受け取る

Posted at

AppleがCombine移行として用意した記事

  • NotificationCenter
  • 非同期処理
  • KVO(Key-Value Observation)
  • Timer処理

の4本です。

今回の記事では「Combineを利用してNotificationCenterでkeyboard関連通知を受け取る」という解説をします。

旧来の書き方

Combineを使わないものでは、ViewControllerなどで以下のような処理を記述していました。

removeObserverを実行している記事もありますが、iOS9以降は不要になっています

old.swift

import UIKit

class ViewController : UIViewController {

    override func viewDidAppear() {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(keyboardWillShow(notification:)),
                                               name: NSNotification.Name.UIKeyboardWillShow,
                                               object: nil)

        NotificationCenter.default.addObserver(self,
                                               selector: #selector(keyboardWillHide(notification:)),
                                               name: NSNotification.Name.UIKeyboardWillHide,
                                               object: nil)
    }

    @objc func keyboardWillShow(notification: Notification) {
        ...
    }

    @objc func keyboardWillHide(notification: Notification) {
       ...
    }

}

Combine利用

Combineではpublisherを利用して記述します。今回はオペレーターをいくつか繋げて、keyboardのフレームを取得するようなコードにしてみます。

receive(on:)は、downstreamの実行スレッドや同期・非同期などを指定できるオペレーターですが、UI周りで使うときはmainスレッドで動いてくれないと予期しない挙動を引き起こすので、必ずRunLoop.mainもしくはDispatchQueue.mainを渡すようにします。

combine.swift

import UIKit
import Combine

class ViewController : UIViewController {
    
    private var cancellables: Set<AnyCancellable> = .init()

    override func viewDidLoad() {
         NotificationCenter
            .default
            .publisher(for: UIResponder.keyboardDidShowNotification, object: nil)
            .compactMap({ $0.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect })
            .receive(on: RunLoop.main)
            .sink { (keyboardFrame) in
                 // 何らかの処理
            }
            .store(in: &cancellables)

        NotificationCenter
            .default
            .publisher(for: UIResponder.keyboardDidHideNotification, object: nil)
            .receive(on: RunLoop.main)
            .sink {
                // 何らかの処理
            }
            .store(in: &cancellables)
    }


}

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?