目标C链接电话

Mir*_*pas 4 cocoa objective-c

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

第一个样本:

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

        return NSApplicationMain(argc, argv);
    }
}
Run Code Online (Sandbox Code Playgroud)

第二个样本:

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

        return NSApplicationMain(argc, argv);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Wil*_*ley 6

详细说明@ tenfour的答案,这一行:

MyCoolDelegate *myCoolDelegate = [[MyCoolDelegate alloc] init];
Run Code Online (Sandbox Code Playgroud)

其中有一个隐含的"__strong",所以它的确意味着:

__strong MyCoolDelegate *myCoolDelegate = [[MyCoolDelegate alloc] init];
Run Code Online (Sandbox Code Playgroud)

如果您将第一行更改为以下内容:

__unsafe_unretained MyCoolDelegate *myCoolDelegate = [[MyCoolDelegate alloc] init];
Run Code Online (Sandbox Code Playgroud)

然后你应该在两种情况下看到相同(坏)的行为.


Vin*_*ble 5

您可能想要创建myCoolDelegate一个实例变量,static变量,或者在xib文件中创建它(就像您从File> New Project ...> Cocoa Application那样获得的Xcode模板).

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

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

通常,-setDelegate:方法不会保留/强引用事物,以防止强引用循环,其中两个对象都保持彼此不被释放.为了兼容性,NSApplication使用__unsafe_unretained对它的引用delegate而不是(通常是可取的)__weak引用(这可能在将来的OS X版本过程中发生变化).因此,当它被解除分配后NSApplication试图与它交谈时delegate,你会崩溃.在delegate这里可以释放,因为没有什么是后强烈引用它-setDelegate:的呼叫.

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

__attribute__((objc_precise_lifetime)) MyCoolDelegate* myCoolDelegate = [[MyCoolDelegate alloc] init];
Run Code Online (Sandbox Code Playgroud)

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