I've developed my own custom Xcode .ideplugin to add a custom object to Xcode's Object Library pane. I have my custom object template based on a class I called IBMyCustomObject, which in turn has a runtimeClassName of a class I called MyCustomObject (a runtime class name is the name of the class that will be instantiated at runtime when the Xib file is loaded).
After tons of research, I've been able to successfully get this working. I can now drag and drop my custom object from the Objects Library pane to Xib files normally, set the object properties in the inspector pane, and everything else is working great. The only problem comes at compile time, where Xcode's ibtool
gives me the following error when the Xib file is compiled:
Exception name: NSInvalidArgumentException
Exception reason: Could not find class named MyCustomObject
And here is the full exception backtrace log:
Exception backtrace:
0. CoreFoundation 0x0226d6d8 __exceptionPreprocess
1. libobjc.A.dylib 0x01fe98b6 objc_exception_throw
2. CoreFoundation 0x022fd721 -[NSException raise]
3. ??? 0x000116b8 [IBCocoaTouchToolObjectPackage initWithRequest:]
4. ??? 0x00010597 [IBCocoaTouchTool .cxx_destruct]
5. ??? 0x0000b63d [IBCocoaTouchTool compileNibForRequest:minimumCompatibility:layoutInfo:]
6. IBFoundation 0x00362c51 __72-[IBMessageReceiveChannel deliverMessage:toTarget:withArguments:result:]_block_invoke
7. IBFoundation 0x00362996 -[IBMessageReceiveChannel deliverMessage:toTarget:withArguments:result:]
8. IBFoundation 0x00362673 __80-[IBMessageReceiveChannel runBlockingReceiveLoopNotifyingQueue:notifyingTarget:]_block_invoke
9. libdispatch.dylib 0x029c2444 _dispatch_barrier_sync_f_slow_invoke
10. libdispatch.dylib 0x029d34b0 _dispatch_client_callout
11. libdispatch.dylib 0x029c1766 _dispatch_main_queue_callback_4CF
12. CoreFoundation 0x022d2b6e __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
13. CoreFoundation 0x022137eb __CFRunLoopRun
14. CoreFoundation 0x02212bf3 CFRunLoopRunSpecific
15. CoreFoundation 0x02212a0b CFRunLoopRunInMode
16. Foundation 0x01c1fe55 -[NSRunLoop(NSRunLoop) runMode:beforeDate:]
17. ??? 0x0003ac67 [IBAbstractCocoaTouchTool startServingReceiveChannel:]
18. ??? 0x0003ad62 [IBAbstractCocoaTouchTool startServingSocket:]
19. ??? 0x0003aec7 [IBAbstractCocoaTouchTool protocolCapabilities]
20. ??? 0x0001053e [IBCocoaTouchTool .cxx_destruct]
21. libdyld.dylib 0x9313d725 start
Exception info:{
}
Any ideas on how can I have Xcode (more specifically ibtool) know about the MyCustomObject class so that it could find it at compile time? I've tried many things, including placing MyCustomObject in a framework and loading the bundle at runtime, but nothing worked at all. If I replace IBMyCustomObject's runtimeClassName with NSMutableDictionary (or any other Foundation or UIKit class) instead of MyCustomObject, everything works perfectly, but I really need to use my own MyCustomObject class instead.
P.S.: For everyone interested in developing similar plugins, I'll be posing all my findings in a detailed blog post on sensiblecocoa.com (the framework using the plugin) once I have everything figured out.
Ok, it turns out that Xcode (more specifically ibtool) is spawning an entirely new process called "Interface Builder Cocoa Touch Tool" during compile time, which explains why loading the MyCustomClass
bundle had no effect. One possible solution to this that I considered was using dylib injection to inject the MyCustomClass
library into the newly spawned process, but none of the techniques I found were reliable enough for robust and stable production code.
I finally ended up using NSMutableDictionary
instead of MyCustomClass
, which compiled perfectly. I then used a setter property method in the object owner class to convert the loaded NSMutableDictionary
into MyCustomClass
, then manually assigned all the dictionary keys to their respective properties. As I said before, I'll be posting all the plugin development details on the sensiblecocoa.com blog page.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With