Skip to content

Instantly share code, notes, and snippets.

@niw
Last active June 21, 2020 15:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niw/b8f2eaa957924b8ea4d29034d7544434 to your computer and use it in GitHub Desktop.
Save niw/b8f2eaa957924b8ea4d29034d7544434 to your computer and use it in GitHub Desktop.
Text View の内容を変更したりすると Undo でクラッシュしたりする原因はこれ

特定のタイミングで setText: すると Undo がおかしくなる、場合によってはクラッシュする問題

  • setText: などの変更は、Text Storage の NSTextStorageDidProcessEditingNotification によって、undoManagergroupingLevel0 の時だけ removeAllActions を呼ぶ。
  • groupingLevel はキーボードから入力があった時は RunLoop が終わらないと 0 にならない。
  • キーボードから入力したときには、coalesceInTextView:affectedRange:replacementRange:replacementText: で、 まず最初に undoManager に Text Storage を target_UITextUndoOperationTypingobject にした Undo が登録される。
  • 次回の入力以降、coalesceInTextView:affectedRange:replacementRange:replacementText: では、 NSUndoManager_shouldCoalesceTypingForText:: (これは::二回で正しい、2つめの引数は名前がない。) を呼んで、 前回の_UITextUndoOperationTyping に変更を追記する方法で入力の Undo を結合するか、新しい Undo を登録するか決めている。 改行の直後などでは新しい Undo が追加される。
  • この挙動があるため、setText: をキーボード入力があった RunLoop の途中で呼ぶと、removeAllActions が呼ばれず、 その結果 Text Storage の内容が変わると、_UITextUndoOperationTyping の内容と齟齬が発生して、場合によってはクラッシュする。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment