トップ «前の日記(2022-12-01) 最新 次の日記(2023-01-30)» 編集

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|

2022-12-02 [Swift]Combine

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() で入力内容をデバッグ出力用テキスト・ビューに設定している。


トップ «前の日記(2022-12-01) 最新 次の日記(2023-01-30)» 編集