objective-c – 目标C链接调用

我是Objective C的新手,所以如果这个问题看起来很愚蠢,请原谅我.

一个样本:

int main(int argc,const char* argv[])
{
    @autoreleasepool
    {
        MyCoolDelegate* myCoolDelegate = [[MyCoolDelegate alloc] init];
        [[NSApplication sharedApplication] setDelegate: myCoolDelegate];

        return NSApplicationMain(argc,argv);
    }
}

第二个样本:

int main(int argc,const char* argv[])
{
    @autoreleasepool
    {
        [[NSApplication sharedApplication] setDelegate: [[MyCoolDelegate alloc] init]];

        return NSApplicationMain(argc,argv);
    }
}

作为C程序员,我希望两个主要函数都应该具有相同的行为,但是返回NSApplicationMain(argc,argv)时会出现第二次主要崩溃;第一个设置委托并按预期工作.

你能解释一下这些样品有什么区别吗? Objective C中的临时对象周围是否有一些黑魔法(我假设[MyCoolDelegate alloc] init]会返回一个MyCoolDelegate类型的临时对象)?

解决方法

你可能想让myCoolDelegate成为一个实例变量,静态变量,或者在xib文件中创建它(比如你从File> New Project …> Cocoa Application做的Xcode模板).

实际上,这两个例子在技术上都是错误的.一个“意外工作”,因为编译器没有(当前!)执行合法优化以在最后一次使用时释放myCoolDelegate,这是在NSApplicationMain调用之前.

Per the spec,“认情况下,自动存储持续时间的局部变量没有精确的生命周期语义.这些对象只是包含可保留对象指针类型值的强引用,并且这些值仍然完全受本地控制下值的优化. “

通常为-setDelegate: methods don’t retain/strongly-reference things,以防止strong reference cycles,其中两个对象都保持彼此不被释放.为了兼容性,NSApplication使用__unsafe_unretained引用它的委托而不是(通常更可取的)__weak引用(这可能会在将来的OS X版本过程中更改).因此,当NSApplication在解除分配后尝试与其委托进行通信时,会发生崩溃.可以在此处取消分配委托,因为在-setDelegate:call之后没有强烈引用它.

总结:使用隐式临时变量或显式局部变量只保持对象存活,直到变量的最后一次使用.只要变量在范围内,它们就不能保证对象保持活动状态.遗憾的是,编译器并没有像它那样具有攻击性,这使得一个显式的局部变量似乎延长了对象的生命周期,而不是保证它.如果您启用了更多优化,则可能会看到不同的行为.您需要使myCoolDelegate成为一种“更长寿”的变量(ivar,staic或global),或者在声明它时使用objc_precise_lifetime属性.

__attribute__((objc_precise_lifetime)) MyCoolDelegate* myCoolDelegate = [[MyCoolDelegate alloc] init];

这种情况很复杂,但实际上并没有出现太多,因为作为另一个对象的委托的事物几乎总是通过ivar或“长寿”来引用,而不仅仅是局部变量.

相关文章

我正在用TitaniumDeveloper编写一个应用程序,它允许我使用Ja...
我的问题是当我尝试从UIWebView中调用我的AngularJS应用程序...
我想获取在我的Mac上运行的所有前台应用程序的应用程序图标....
我是一名PHP开发人员,我使用MVC模式和面向对象的代码.我真的...
OSX中的SetTimer在Windows中是否有任何等效功能?我正在使用...
我不确定引擎盖下到底发生了什么,但这是我的设置,示例代码和...