Got few crash reports from macOS 14.0. After digging deep I found that issue is related to keypath bindings(NSDisplayPatternValueBinding) with NSObjectController and NSTextView. I bind NSTextView to NSObjectController in storyboard and set content of NSObjectController in code. Content is a simple String wrapper.
The problem occurs when I use keypath with "dot" (text.length). If I set string value for known system defined text replacement ("On my way!") during unarchiving from the nib - the app will crash with below error message. However, if the value is not in text replacement dictionary it won't crash. Similarly it won't crash for simple non-dot keypath. It won't crash if I change my model object to NSString
Is this macOS Sonoma bug or I use bindings in way I shouldn't?
Error messages (exception breakpoint):
(lldb) po $x0
Cannot remove an observer <NSKeyValueObservance 0x6000031d0030> for the key path "length" from <Swift.__StringStorage 0x600002a7fa80> because it is not registered as an observer.
(null)
(lldb) po $x0
Cannot update for observer <NSObjectController 0x600000e78500> for the key path "text.length" from <KVOTextViewIssue.DymmyObject 0x600003f713a0>, most likely because the value for the key "text" has changed without an appropriate KVO notification being sent. Check the KVO-compliance of the KVOTextViewIssue.DymmyObject class.
(null)
(addresses are mixed, not the problem of having different nsobjectcontroller)
Failed to set (contentViewController) user defined inspected property on (NSWindow): Cannot update for observer <NSObjectController 0x6000027f6620> for the key path "text.length" from <KVOTextViewIssue.DymmyObject 0x6000016be100>, most likely because the value for the key "text" has changed without an appropriate KVO notification being sent. Check the KVO-compliance of the KVOTextViewIssue.DymmyObject class.
Minimum reproducible example:
final class DymmyObject : NSObject {
@objc dynamic var text : String = "On my way!" //CRASHES
//@objc dynamic var text : NSString = "On my way!" //DOES NOT CRASH
//@objc dynamic var text : String = "Hello" //DOES NOT CRASH
}
class ViewController: NSViewController {
@IBOutlet var textView: NSTextView!
@IBOutlet var objectController: NSObjectController! {
didSet {
representedObject = dummy
}
}
var dummy : DymmyObject = DymmyObject()
override func viewDidLoad() {
super.viewDidLoad()
self.textView.insertText("123", replacementRange: NSMakeRange(0, 0))
}
}
Digging deep - noticed that background thread on crash was spellchecker




Bumping the minimum macOS deployment target from 10.13 to 10.14 solves the crashing/issue on Sonoma.