- 
                Notifications
    You must be signed in to change notification settings 
- Fork 8
Understanding load order of classes and categories
The runtime loads classes, strings and categories.
The addition of a class or category is delayed until all requirements have been met. A category or class may be delayed indefinetely. Strings are added immediately, but they remain unusable until the static string classes (usually NSConstantString and tagged pointer string classes) get loaded.
A class can be added to the runtime only, if the following conditions are met:
- Its superclass must be present
- The classes and categories enumerated by +dependenciesmust be present
- The protocol classes of the class must be present (except if it IS the protocol class)
+dependenciesis a new feature in mulle-objc 0.6.x
Avoid circular dependencies:
@class Foo; @protocol Foo @end @class Bar; @protocol Bar @end @interface Bar <Foo> @end @interface Foo <Bar> @end
A category can be added to the runtime only, if the following conditions are met:
- Its class must be present
- The classes and categories enumerated by +dependenciesmust be present
- The protocol classes of the category must be present
Assume you have a class Foo, which categories a, b. You want the load order to be Foo, Foo(a), Foo(b).
Specify:
@implementation Foo( b)
+ (struct _mulle_objc_dependency *) dependencies
{
    static struct _mulle_objc_dependency   dependencies[] =   
    {
       { @selector( Foo), @selector( a) },
       { 0, 0 }
    };
    return( dependencies);
}
@end
Foo and Foo( a) are sequenced properly already by the requirement, that a class is loaded before its categories are loaded. You want to make sure that Foo( b) appears after Foo( a) though.
If you can stick a Foundation library and the application in separate shared libraries, any +load method in the application will find the full set of Foundation functionality available. Problems arise, when you can't or don't want to layer your code with shared libraries.
Then a +load in the application may encounter the Foundation in a partially initialized state. Possibly NSAutoreleasePool for example, may not be present yet!
- Your class exists and can be messaged
- All super classes exist and can be messaged (but they may not have their categories yet!)
- All protocol classes exist and can be messaged (they should not have categories anyway)
- All classes and categories listed in +dependenciesexist and can be messaged
Everything else may not be there or may not be initialized. For example a constant NSString like @"VfL Bochum 1848" may not be usable yet, unless you put { @selector( NSConstantString), 0 } into the list returned by +dependencies.
- Your class exists and can be messaged
- All super classes exist and can be messaged (but they may not have their categories yet!)
- All protocol classes exist and can be messaged (they should not have categories anyway)
- All categories and classes listed in +dependenciesexist and can be messaged.
- If you code a +loadfunction and you stick with C, you should have no problems.
- If you need to use Objective-C, do not declare dependencies on abstract classes like NSString. Use concrete classes like 'NSConstantString".
- It's a good idea to check for stuck classes and categories at the start of main():#if defined( __MULLE_OBJC__) && defined( DEBUG) mulle_objc_check_runtime(); #endif
- It is a good idea to create a "Foundation" class, that depends on all other categories and classes in the Foundation. That way a user only need to specify his +dependenciesonly on this Foundation class to have a complete Foundation ready before his+loadis run. The MulleFoundation will do this.