Search code examples
objective-ccocoaappkit

crash in `[NSApp run]` when delegate is not referenced anymore


This is the code:

@interface AppDelegate : NSObject <NSApplicationDelegate>

@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    printf("My app delegate: finish launching\n");
}

@end

int main(int argc, char *argv[])
{
    @autoreleasepool
    {

        [NSApplication sharedApplication];
        [NSApp setDelegate:[[AppDelegate alloc] init]];
        [NSApp run];
    }
}

It crashes in [NSApp run] but I don't really see what I'm missing. If I add an [NSApp finishLaunching] before the run, it crashes in there.

If I don't set the delegate, it doesn't crash.

If I reference the delegate before, it works fine:

AppDelegate* appDelegate = [[AppDelegate alloc] init];
[NSApp setDelegate:appDelegate];

So I guess it releases the delegate immediately in the first version because of ARC and because the delegate is probably only a weak reference, right? But how are you supposed to do the same code otherwise?


Solution

  • Yes you guess right, NSApplication don't retain the delegate, (weak reference with ARC). So you can just build the main.m file with -fno-objc-arc with you current code :

    int main(int argc, char *argv[])
    {
        @autoreleasepool
        {
            [NSApplication sharedApplication];
            [NSApp setDelegate:[[AppDelegate alloc] init]];
            [NSApp finishLaunching];
            [NSApp run];
        }
    }
    

    or set you AppDelegate static in main.m, for example, and build with ARC

    static AppDelegate* _appDelegate;
    
    int main(int argc, char *argv[])
    {
        @autoreleasepool
        {
            _appDelegate = [[AppDelegate alloc] init];
            [NSApplication sharedApplication];
            [NSApp setDelegate:_appDelegate];
            [NSApp run];
        }
    }