この記事では、NSTextStorageDelegate についてです。
Sponsor Link
環境&対象
- macOS Sonoma Beta 4
- Xcode 15 Beta 5
- iOS 17 Beta 4
- Swift 5.9
NSTextStorageDelegate
NSTextStorageDelegate は、NSTextStorage が変更された時に呼び出される Delegate です。
Apple のドキュメントは、こちら。
2つの メソッドが定義されています。
macOS と iOS では少しだけ シグネチャが異なりますが、意味は同じです。
macOS
optional func textStorage(
_ textStorage: NSTextStorage,
willProcessEditing editedMask: NSTextStorageEditActions,
range editedRange: NSRange,
changeInLength delta: Int
)
optional func textStorage(
_ textStorage: NSTextStorage,
didProcessEditing editedMask: NSTextStorageEditActions,
range editedRange: NSRange,
changeInLength delta: Int
)
iOS
optional func textStorage(
_ textStorage: NSTextStorage,
willProcessEditing editedMask: NSTextStorage.EditActions,
range editedRange: NSRange,
changeInLength delta: Int
)
optional func textStorage(
_ textStorage: NSTextStorage,
didProcessEditing editedMask: NSTextStorage.EditActions,
range editedRange: NSRange,
changeInLength delta: Int
)
willProcessEditing と didProcessEditing は 変更処理の前後で それぞれ呼ばれます。
以下の調査は、iOS simulator 上で、didProcessEditing を使って調査しました。
macOS 上でも/willProcessEditing でも 同じだと思いますが確認はしていません。
呼び出し時の引数
willProcessEditing も didProcessEditing も引数は同じです。
それぞれの意味を確認します。
- textStorage
- 変更されている NSTextStorage が渡されてきます。
- didProcessEditing/willProcessEditing: NSTextStorage.EditActions/NSTextStorageEditActions
- editedCharacters のときは文字が変更され、editedAttributes の時は、文字のアトリビュートが変更されています(その両方が変更されていることもあります)
- range: NSRange
- 変更された 領域情報が NSRange で渡されてきます
- changeInLength: Int
- 変更された文字数が Int で渡されてきます
以降では、NSTextStorage の “01234” という文字列が変更された時に渡されてくる range: NSRange と chandeInLength: Int を確認してみます。
# 以降では、didProcessEditing に渡されてくる値を確認しています。
文字列追加時
通常想定される(?) NSRange と Int が渡されてきます。
つまり、追加された文字列の区間をしめす NSRange と全体の文字数がどの様に変化したかを表す Int が渡されてきました。
先頭に追加
”01234” を “901234” と変更しました。
range: (location: 0, length: 1)
changeInLength: 1
中間に追加
”01234” を “019234” と変更しました。
range: (location: 2, length: 1)
changeInLength: 1
末尾に追加
”01234” を “012349” と変更しました。
range: (location: 5, length: 1)
changeInLength: 1
文字列削除時
文字列削除の時の NSRange には、削除された区間の情報が渡されるかと期待したのですが、違いました。
削除だからといっても、NSRange の length に 負の値が設定されてくることもありませんでした。
NSRange の location は、削除される文字の位置でした。複数文字がまとめて削除されるときは、文字列の先頭位置でした。
NSRange の length は、常に 0 です。
削除された文字数は、changeInLength を確認することが必要となります。
なお、Delete でも BackSpace でも同じ値が渡されてきました。
先頭を削除
”01234” を “1234” と変更しました。
range: (location: 0, length: 0)
changeInLength: -1
”01234” を “234” と変更しました。(2文字(01)選んで1操作で削除してます)
range: (location: 0, length: 0)
changeInLength: -2
中間を削除
”01234” を “0134” と変更しました。
range: (location: 2, length: 0)
changeInLength: -1
”01234” を “014” と変更しました。(2文字(23)選んで1操作で削除してます)
range: (location: 2, length: 0)
changeInLength: -2
末尾を削除
”01234” を “0123” と変更しました。
range: (location: 4, length: 0)
changeInLength: -1
”01234” を “012” と変更しました。(2文字(34)選んで1操作で削除してます)
range: (location: 3, length: 0)
changeInLength: -2
置き換え時
置き換え時には、期待通り 置き換えた部分の情報が NSRange として渡されてきます。
置き換えられた範囲が、NSRange として渡されてきて、文字列全体の増減を表す Int が渡されます。
文字列追加の時と同じです。
先頭を置換
”01234” を “91234” と変更しました。
range: (location: 0, length: 1)
changeInLength: 0
”01234” を “891234” と変更しました。
range: (location: 0, length: 2)
changeInLength: 1
中間を置換
”01234” を “01934” と変更しました。
range: (location: 2, length: 1)
changeInLength: 0
”01234” を “018934” と変更しました。
range: (location: 2, length: 2)
changeInLength: 1
末尾を置換
”01234” を “01239” と変更しました。
range: (location: 4, length: 1)
changeInLength: 0
”01234” を “012389” と変更しました。
range: (location: 4, length: 2)
changeInLength: 1
まとめ
NSTextStorageDelegate の textStorage(:,willProcessEditing:,range:,changeInLength:) と
textStorage(:,didProcessEditing:,range:,changeInLength:) が 呼び出される時に受け取る引数について確認しました。
- range は、追加時/削除時で意味が少し異なる
- changeInLength は、文字列の増減数
- iOS と macOS ではシグネチャが少し異なるのでコードを共有するときは工夫が必要
説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。
SwiftUI おすすめ本
SwiftUI を理解するには、以下の本がおすすめです。
SwiftUI ViewMatery
SwiftUI で開発していくときに、ViewやLayoutのための適切なmodifierを探すのが大変です。
英語での説明になってしまいますが、以下の”SwiftUI Views Mastery Bundle”という本がビジュアル的に確認して探せるので、便利です。
英語ではありますが、1ページに コードと画面が並んでいるので、非常にわかりやすいです。
View に適用できる modifier もわかりやすく説明されているので、ビューの理解だけではなく、どのような装飾ができるかも簡単にわかります。
超便利です
販売元のページは、こちらです。
SwiftUI 徹底入門
# SwiftUI は、毎年大きく改善されていますので、少し古くなってしまいましたが、いまでも 定番本です。
Swift学習におすすめの本
詳解Swift
Swift の学習には、詳解 Swift という書籍が、おすすめです。
著者は、Swift の初期から書籍を出していますし、Swift の前に主力言語だった Objective-C という言語についても同様の書籍を出しています。
最新版を購入するのがおすすめです。
現時点では、上記の Swift 5 に対応した第5版が最新版です。
Sponsor Link