The problem was due to the fact that our custom view class was not registered with the runtime. Apple's documentation clearly states that when a class has been allocated and its methods and what not set, the final step before using the class is to register it with the runtime by calling objc_registerClassPair. Not heeding this results in undefined behavior, one of those being the crash we witnessed.
Precisely how that led to the crash
Objective-C runtime offers a unique feature called Key-Value Observing (KVO) where you can observe for changes on properties of any derived class of NSObject as long as the property meets the definition criteria. It turns out that the Webkit implementation under the hood makes use of this in some blackbox manner in order to implement docked windows, which is used for the Developer Tools window of the WebView when it is docked.
Well, the way KVO is implemented under the hood is that the runtime calls objc_duplicateClass on the class being observed in order to clone this class and dynamically create a new class from this and setup the machinery required for the key-value observation to work. My strong suspicion is that this call will fail if the class has not been registered. Perhaps according to the runtime, a class that is not registered doesn't exist for practical purposes. (The fact that it works for most things that we have encountered so far except this KVO thing is really annoying...it would have been much more helpful had the app crashed much earlier with a more helpful description so that we could have caught this much earlier...but that's apple engineering for you).
What further confirms the above hypothesis is the following exception logged when running the app under lldb:
2023-04-21 01:05:31.916943-0400 parsecd[37300:14529429] [general] KVO failed to allocate class pair for name NSKVONotifying___mty_app_view_0, automatic key-value observing will not work for this class
objc[37300]: no class for metaclass 0x600000c214d0
The runtime tried to clone our view class in order to create the KVO clone as discussed earlier but it failed to allocate it due to the reason no class for metaclass. This strongly hints that it couldn't FIND the class, which would make sense if the class wasn't registered. QED
The problem was due to the fact that our custom view class was not registered with the runtime. Apple's documentation clearly states that when a class has been allocated and its methods and what not set, the final step before using the class is to register it with the runtime by calling
objc_registerClassPair
. Not heeding this results in undefined behavior, one of those being the crash we witnessed.Precisely how that led to the crash
Objective-C runtime offers a unique feature called Key-Value Observing (KVO) where you can observe for changes on properties of any derived class of
NSObject
as long as the property meets the definition criteria. It turns out that the Webkit implementation under the hood makes use of this in some blackbox manner in order to implement docked windows, which is used for the Developer Tools window of the WebView when it is docked.Well, the way KVO is implemented under the hood is that the runtime calls
objc_duplicateClass
on the class being observed in order to clone this class and dynamically create a new class from this and setup the machinery required for the key-value observation to work. My strong suspicion is that this call will fail if the class has not been registered. Perhaps according to the runtime, a class that is not registered doesn't exist for practical purposes. (The fact that it works for most things that we have encountered so far except this KVO thing is really annoying...it would have been much more helpful had the app crashed much earlier with a more helpful description so that we could have caught this much earlier...but that's apple engineering for you).What further confirms the above hypothesis is the following exception logged when running the app under lldb:
The runtime tried to clone our view class in order to create the KVO clone as discussed earlier but it failed to allocate it due to the reason
no class for metaclass
. This strongly hints that it couldn't FIND the class, which would make sense if the class wasn't registered. QED