Skip to content

Understanding load order of classes and categories

Nat! edited this page Apr 6, 2017 · 8 revisions

partly 0.4.0 content

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.

Class requirements

  1. It's superclass must be present
  2. The classes enumerated by +classDependencies must be present
  3. The protocol classes of the class must be present (except if it IS the protocol class)

Avoid circular dependencies:

@class Foo;
@protocol Foo
@end

@class Bar;
@protocol Bar
@end

@interface Bar <Foo>
@end
@interface Foo <Bar>
@end

Category requirements

  1. It's class must be present
  2. The categories on this class enumerated by +categoryDependencies must be present
  3. The protocol classes of the category must be present

+categoryDependencies is a new feature in mulle-objc 0.4.x

Specifiying +categoryDependencies

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)

+ (SEL *) categoryDependencies
{
    static SEL   dependencies[] =   
    {
       @selector( a),
       0
    };

    return( dependencies);
}

@end

Foo and Foo( a) are sequenced properly already by the requirements. You just want to make sure that Foo( b) appears after Foo( a).

Managing +load order

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!

What to expect, when you are inside +load of a class

  1. Your class exists and can be messaged
  2. All super classes exist and can be messaged (but they may not have their categories yet!)
  3. All protocol classes exist and can be messaged (they should not have categories anyway)
  4. All classes with classids listed in +classDependencies exist and can be messaged (but they may not have their categories yet!)

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) into the list of classids returned by +classDependencies.

What to expect, when you are inside +load of a category

  1. Your class exists and can be messaged
  2. All super classes exist and can be messaged (but they may not have their categories yet!)
  3. All protocol classes exist and can be messaged (they should not have categories anyway)
  4. All categories of the same class with categories listed in +categoryDependencies exist and can be messaged.

It is a bad idea to speculate on any other class existing besides your own class. If you category depends on another class, the class must specify this dependency in +classDependencies. A +classDependencies in the category is ignored.

Tips

If you code a +load function and you stick with C, you should have no problems. If you need to use Objective-C, declare the classes you want to use in +classDependencies. Do not declare abstract classes like NSString use concrete classes like 'NSConstantString". Be sure that the functionality you are expecting is not part of a category!

Clone this wiki locally