-
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
+dependencies
must be present - The protocol classes of the class must be present (except if it IS the protocol class)
+dependencies
is 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
+dependencies
must 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
+dependencies
exist 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
+dependencies
exist and can be messaged.
- If you code a
+load
function 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
+dependencies
only on this Foundation class to have a complete Foundation ready before his+load
is run. The MulleFoundation will do this.