views:

61

answers:

3

This is a weird one. On and off as I have been working on my application, this problem has popped up, and then it has always mysteriously vanished. Today it is refusing to vanish.

My app uses two view controllers to handle auto rotation. Sometimes, Objective-C can't find my classes. For example [OneViewController alloc] will crash. I added a function to catch this state, and even if I call it before I run a single line of my own code, things are still broken. I take this to prove that whatever is wrong, it is not with any bad code I may have written.

Anyone have any idea why universalGoodness would not be a constant?

void verifyUniversalGoodness()
{
 id portrait_class, landscape_class;

 portrait_class = NSClassFromString(@"OneViewController");
 landscape_class = NSClassFromString(@"OtherViewController");
 NSLog(@"CHECKING GOODNESS: portrait %@, landscape %@", portrait_class, landscape_class);
 if (portrait_class == nil || landscape_class == nil)
  exit(0);
}

int main( int argc, char *argv[] )
{
    verifyUniversalGoodness();

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;

}

Here's what a stack trace looks like if I let it run to call of alloc ...

#1  0x3356296c in _class_initialize ()
#2  0x33567dfe in prepareForMethodLookup ()
#3  0x33565168 in lookUpMethod ()
#4  0x33562914 in _class_lookupMethodAndLoadCache ()
#5  0x3356264a in objc_msgSend_uncached ()
#6  0x000de704 in -[MyAppDelegate finishStartup] (self=0x61c9a0, _cmd=0x303117) at /Users/michael.toy/PROJECT/MyAppDelegate.mm:180
#7  0x32b77904 in __NSFireDelayedPerform ()
#8  0x32c23d22 in CFRunLoopRunSpecific ()
#9  0x32c234e0 in CFRunLoopRunInMode ()
#10 0x30d620da in GSEventRunModal ()
#11 0x30d62186 in GSEventRun ()
#12 0x314d54c8 in -[UIApplication _run] ()
#13 0x314d39f2 in UIApplicationMain ()
#14 0x000e13a8 in main (argc=1, argv=0x2ffff5a8) at /Users/michael.toy/PROJECT/main.mm:38
A: 

I don't know the answer, but I was struck by the different wording on NSClassFromString() and NSBundle's -(Class)classNamed:(NSString *)className

"The class object named by aClassName, or nil if no class by that name is currently loaded*. If aClassName is nil, returns nil."

vs

"The Class object for className. Returns nil if className is not one of the classes associated with the receiver or if there is an error loading the executable code containing the class implementation."

So NSClassFromString() doesn't seem to imply an order to actually load the class.

mvds
True, however, if my source code says:- (void) finishStartup{ verifyUniversalGoodness(); id x = [OneViewController alloc];}This should either not link, or work. According to my tiny brain.
mtoy
... and just to be sure I tried calling NSBundle classNamed ... same problem, classNamed can't find a class which is staticly linked into the binary -- or that is what it looks like
mtoy
A: 

portrait_class/landscape_class should be a Class object, not id object:

typedef struct objc_class *Class;
typedef struct objc_object {
    Class isa;
} *id;

(That's from objc.h)

digdog
Won't make a difference, they are both valid receiver types.
dreamlax
... and all I care about is, "are they nil"
mtoy
+1  A: 

Thank you for all your responses. It got me looking closer at the problem. It turns out that the class I care about is in one library, and the main is in another library, and both libraries are linked into my final binary.

I needed to add -Wl,-ObjC to my link line, and that seems to have fixed things and universalGoodness is now restored. I have no idea what triggered the state where this was needed, but I am happy to be back in business.

mtoy
Neat. You should select this as the answer to this question.
Jonathan Sterling