【问题标题】:Why is applicationWillFinishLaunching in my NSApplicationDelegate class never called?为什么我的 NSApplicationDelegate 类中的 applicationWillFinishLaunching 从未被调用?
【发布时间】:2010-02-11 08:22:00
【问题描述】:

main.m

#import <Cocoa/Cocoa.h>

int main(int argc, char *argv[])
{
    return NSApplicationMain(argc,  (const char **) argv);
}

CoolClass.h

#import <Cocoa/Cocoa.h>

@interface CoolClass : NSObject <NSApplicationDelegate> {

}
- (void) applicationDidFinishLaunching : (NSNotification *) aNotification;
@end

CoolClass.m

#import "CoolClass.h"

@implementation CoolClass
- (void) applicationDidFinishLaunching : (NSNotification *) aNotification {
    NSLog(@"THIS SHOULD BE PRINTED TO THE DEBUG CONSOLE");
}

@end

我也尝试过使用“applicationWillFinishLaunching”,但仍然没有运气。任何帮助将不胜感激。谢谢。

【问题讨论】:

    标签: objective-c cocoa xcode delegates


    【解决方案1】:

    您缺少的是采用该协议使 CoolClass 类型的对象准备好充当任何 NSApplication 对象的委托(前提是您遵循声明并实现协议的所有必需方法)。当您将类的实例设置为应用程序的委托时,声明符合协议还可以防止编译器警告。

    但是对于特定的应用程序对象(例如,Cocoa 为您创建的共享 NSApplication 对象)要知道将消息从协议发送到特定的 CoolClass 对象,您必须将要接收这些消息的对象设置为特定的应用程序对象的委托。

    这意味着在应用程序发送您想要接收的消息之前的某个时间,需要实例化一个 CoolClass 对象 - 称之为 c - 并告诉应用程序,“嘿,你的代表是 @ 987654322@ 这边,从现在开始给小家伙发送委托消息。”

    归结为,这些代码行必须在应用程序完成启动之前执行:

    CoolClass *c = [[CoolClass alloc] init];
    [[NSApplication sharedApplication] setDelegate:c];
    

    发生这种情况的最简单方法是让 Interface Builder 为您完成工作:让 MainMenu nib 实例化您的 CoolClass 并在加载 nib 时将酷类对象设置为应用程序的委托,正如其他人所建议的那样。

    为此,请打开 MainMenu.xib。将自定义对象拖入 xib 并在检查器中将其类更改为 CoolClass。从 xib 中的应用程序对象按住 Ctrl 并拖动(或右键单击拖动)到 CoolClass 对象并选择“委托”。保存、构建并运行。

    【讨论】:

      【解决方案2】:

      您应该在 Interface Builder 中将您的 CoolClass 定义为应用程序委托(Ctrl+Drag 从 App 实例到您的 CoolClass 实例

      【讨论】:

      • 或者,如果您想以编程方式进行,您可以在CoolClass-init 方法中调用[NSApp setDelegate:self]
      • 啊,刚看到上面的评论。我会试试的。
      • 我目前有:CoolClass.m #import "CoolClass.h" @implementation CoolClass - (void) init{ [NSApp setDelegate:self]; NSLog(@"这应该打印到调试控制台"); } @end 但它仍然不会运行。我也修改了 CoolClass.h 以反映这一点。我对上面的答案感到困惑。我应该拖什么,拖到哪里?
      • 将 [Object] 从界面生成器中的组件库拖到 MainMenu.xib。然后在身份检查器中将其类设置为 CoolClass。然后做 ctrl+drag 技巧。
      【解决方案3】:

      applicationDidFinishLaunching 是实例方法,而不是类方法。也就是说,您需要类的实例化才能接收该消息。另外,它不能只是-任何-实例化;您的应用程序需要了解您的实例化并知道它应该向它发送委托消息。最简单和最常见的方法是...

      首先,您将实例化您的 CoolClass。在 Interface Builder 中打开应用程序的 MainMenu.nib 文件。将“对象”(它看起来像一个蓝色立方体)拖出库窗口。选择它并使用 Inspector 的 Identity 选项卡将其类从 NSObject 更改为 CoolClass。现在,您有了 CoolClass 的一个实例。

      现在,您将该实例设置为应用程序的委托。按住 Control 从“Application”(仍在 Interface Builder 中)拖动到新的 CoolClass 实例。将弹出一个窗口(显示可以连接到您的对象的应用程序的出口)。选择“委托”。现在,您的应用程序有一个 CoolClass 实例作为其委托,因此,您的 applicationDidFinishLaunching 将运行。

      【讨论】:

      • 如果您采用 并且不实现 -applicationDidFinishLaunching(带有选择器 @selector(applicationDidFinishLaunching) 的实例方法),您将收到编译器警告,但如果您实现 +applicationDidFinishLaunching(使用选择器 @selector(applicationDidFinishLaunching)) 的类方法并将类本身设置为应用程序的委托 ([[NSApplication sharedApplication] setDelegate:[CoolClass class]]),应用程序对象将向 CoolClass 本身发送消息。
      • 在 Swift Xcode 10.1 中,我在 (My)CoolClass.init() 中添加了 NSApplication.shared.delegate = self 行,效果很好
      【解决方案4】:

      感谢您尝试从头开始学习,但您为什么不直接使用其中一个 XCode 模板创建一个新项目?它为您设置了这一切。生活需要足够的调试,而不必在上面添加更多!

      【讨论】:

      • 在大项目中很难做到。将 50 个旧工作文件推送到一个新项目中是一件很麻烦的事情。也许是我,但是......
      【解决方案5】:

      从头开始:您对NSApplicationMain 的调用应包含在NSAutoreleasePool 中。如果你不这样做,你会遇到麻烦。

      【讨论】:

        猜你喜欢
        • 2017-08-22
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多