我是ObjC / Cocoa和Mac开发的新手,并且玩弄了基础知识。
Lion上的Xcode 4.2中新的Cocoa应用程序的简单默认模板如下所示:
// AppDelegate.h
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (assign) IBOutlet NSWindow *window;
@end
// Appdelegate.m
#import "AppDelegate.h"
@implementation AppDelegate
@synthesize window = _window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
}
@end
我一直在用它作为各种实验的基础。阅读自动引用计数(项目设置使用) - 例如this article - 我假设可以,甚至应替换assign
限定符NSWindow *window
与weak
,但似乎并非如此。
该应用构建正常,但在启动期间挂起,Thread 1: Program received signal: "EXC_BAD_INSTRUCTION"
位于AppDelegate.m
的{{1}}行。{/ p>
将限定符更改为@synthesize window = _window;
会使该程序正常运行,但我无法看到从strong
转到assign
有何意义。我的印象是,非ARC / ARC的配对分配/弱,保留/强。
更有经验的编码朋友建议,即使strong
限定符导致weak
过早释放,并且某些访问尝试失败,例外也应为window
,而不是EXC_BAD_ACCESS
{1}}。
我显然在这里遗漏了一些东西,但我不知道是什么。
编辑:仔细查看崩溃时gdb输出后,同一位朋友向我指出this article by Mike Ash对此有所了解。由于我理解的原因,EXC_BAD_INSTRUCTION
和其他一些覆盖NSWindow
和retain
的类不能成为归零弱引用的目标。有趣的是,将属性声明更改为有效:
release
...即使Apple's documentation for Declared Properties中未提及@property (unsafe_unretained) IBOutlet NSWindow *window;
。
有了这个,已经修改过的问题:
什么是正确的方式去这里?坚持unsafe_unretained
尽管在网上提到它不应该与ARC一起使用?转到assign
?继续使用strong
因为它似乎有用吗?还有别的吗?
答案 0 :(得分:8)
从概念上讲,'弱'是OS X上顶级IBOutlet的正确限定符(iOS是另一个故事)。但是,要创建一个适当的弱引用,在重新分配时为零需要来自Objective C运行时的协作。覆盖保留或释放的类会破坏此支持,因此您无法创建对它们的弱引用。 UIWindow就是这样一个类。
这就是模板使用'assign'的原因。如果启用ARC,也许应该使用同义词'unsafe_unretained'。在任何一种情况下,你都有一个不归零的简单弱引用。
答案 1 :(得分:3)
Mike Ash的博客讨论了一些Cocoa类的问题。
在页面的中间部分查找:Friday Q&A ARC。查看/搜索以“ARC实现归零弱引用...”开头的文本
问题是某些类不处理__weak带来的归零弱引用。解决方案是使用普通ARC模板提供的 assign 。
嗯,回答第二个问题,即使Apple的模板在使用ARC时也使用窗口分配。所以你现在可能很安全。但是你的里程可能在将来有所不同。
答案 2 :(得分:2)
Mike Ash has a very good explanation of what's going wrong here(搜索“ARC的实施”)。它的要点是NSWindow类特别不支持弱引用:显然是因为它依赖于覆盖保留和释放以及它自己的实现。
我希望在遗留的Cocoa类中分散更多这样的问题,而这些问题似乎还没有记录 - 相反,你会发现运行时错误。 (我希望在某些时候这也会成为编译器警告。)