iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど
Combineはイベント処理演算子を組み合わせて、非同期でイベントを処理するSwiftのAPIだ。
既存のNotificationCenterやAppKitとUIKitのUI部品はCombineに対応しているので、Combineのイベント処理演算子の使ったイベント処理が行える。
例えば、テキスト入力フィールドとデバッグ出力用テキスト・ビューがあるNSViewControllerの派生クラスがあるとする。
import Cocoa
import Combine
class ViewController: NSViewController {
@IBOutlet var inputField: NSTextField!
@IBOutlet var debugMessageTextView: NSTextView!
var sub: AnyCancellable? = nil
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
inputFieldにテキストが入力されたら、そのイベントを受け取りたい場合は、以下のコードとなる。
override func viewDidLoad() {
super.viewDidLoad()
sub = NotificationCenter.default
.publisher(for: NSControl.textDidChangeNotification, object: inputField)
.sink(receiveCompletion: { print ($0) },
receiveValue: { print ($0) })
}
sink() はイベントを受け取るもので、こんな感じでイベント処理演算子をつなげていることになる。
override func viewDidLoad() {
super.viewDidLoad()
sub = NotificationCenter.default
.publisher(for: NSControl.textDidChangeNotification, object: inputField)
.map( { ($0.object as! NSTextField).stringValue } )
.filter( { $0.unicodeScalars.allSatisfy({CharacterSet.alphanumerics.contains($0)}) } )
.debounce(for: .milliseconds(500), scheduler: RunLoop.main)
.receive(on: RunLoop.main)
.assign(to:\NSTextView.string, on: debugMessageTextView)
}
上の例のコードを説明する。
map() で文字列に変換している。
filter() で英数字のみとしている。
debounce() でイベント発行の頻度を調整している。
receive() でメイン・スレッドで受け取るようにしている。
assign() で入力内容をデバッグ出力用テキスト・ビューに設定している。