EXC_BAD_INSTRUCTION 合成 @property 时(弱) IBOutlet NSWindow *window

发布于 2024-12-11 22:40:44 字数 2070 浏览 0 评论 0 原文

一般来说,我是 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

我一直使用它作为各种实验的基础。阅读自动引用计数(项目设置使用)—这篇文章,我认为可以甚至应该应该替换 NSWindow 的 assign 限定符*windowweak,但情况似乎并非如此。

该应用程序构建良好,但在启动期间挂起,AppDelegate.m 中的线程 1:程序收到信号:“EXC_BAD_INSTRUCTION” 位于 @synthesize window = 行上_窗口;

将限定符更改为 strong 可以使程序正常运行,但我不明白从 assign 更改为 strong 有何意义。我的印象是非 ARC/ARC 的配对是分配/弱和保留/强。

一位更有经验的程序员朋友建议,即使 weak 限定符导致 window 过早释放并且对它的某些访问尝试失败,异常也应该是 EXC_BAD_ACCESS< /code>,而不是 EXC_BAD_INSTRUCTION

我显然在这里遗漏了一些东西,但我不知道是什么。

编辑:仔细查看崩溃时 gdb 输出后,同一个朋友向我指出 Mike Ash 的这篇文章对此进行了一些阐述。由于超出我理解的原因,NSWindow和其他一些重写retainrelease的类不能成为弱引用清零的目标。有趣的是,将属性声明更改为此有效:

@property (unsafe_unretained) IBOutlet NSWindow *window;

...即使 Apple 的声明属性文档

有了这个,修订后的问题

到达这里的正确方法是什么?尽管网络上提到它不应该与 ARC 一起使用,但仍坚持使用 assign?追求?继续使用 unsafe_unretained 因为它似乎有效吗?还有别的事吗?

I'm a newbie to ObjC/Cocoa and Mac development in general, and toying with the basics.

The simplistic default template for a new Cocoa application in Xcode 4.2 on Lion looks like this:

// 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

I've been using that as a basis for various experiments. Reading up on Automatic Reference Counting (which the project is set to use)—this article, for example—I assumed that one could, perhaps even should replace the assign qualifier for NSWindow *window with weak, but that does not seem to be the case.

The app builds fine, but hangs during startup, with Thread 1: Program received signal: "EXC_BAD_INSTRUCTION" in AppDelegate.m on the line with @synthesize window = _window;.

Changing the qualifier to strong makes the program work, but I fail to see how it would make sense to go from assign to strong. I'd gotten the impression that the pairings for non-ARC/ARC are assign/weak and retain/strong.

A more experienced coder friend suggested that even if the weak qualifier causes window to be prematurely deallocated and some access attempt on it to fail, the exception should be EXC_BAD_ACCESS, not EXC_BAD_INSTRUCTION.

I'm obviously missing something here, but I have no idea what.

EDIT: After a closer look at the crash-time gdb output, the same friend pointed me to this article by Mike Ash that sheds some light on this. Due to reasons beyond my understanding, NSWindow and some other classes that override retain and release can't be the target of zeroing weak references. Interestingly, changing the property declaration to this works:

@property (unsafe_unretained) IBOutlet NSWindow *window;

...even though unsafe_unretained isn't mentioned in Apple's documentation for Declared Properties.

With that, a REVISED QUESTION:

What would be the proper way to go here? Stick to assign despite mentions around the web that it shouldn't be used with ARC? Go for strong? Keep using unsafe_unretained since it seems to work? Something else?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凉薄对峙 2024-12-18 22:40:45

从概念上讲,“弱”是 OS X 上顶级 IBOutlet 的正确限定符(iOS 是另一个故事)。然而,要创建一个在释放时归零的适当的弱引用,需要 Objective C 运行时的配合。重写保留或释放的类会破坏这种支持,因此您无法创建对它们的弱引用。 UIWindow 就是这样的一个类。

这就是模板使用“分配”的原因。如果启用了 ARC,也许它确实应该使用同义词“unsafe_unretained”。无论哪种情况,您都会有一个未归零的简单弱引用。

Conceptually, 'weak' is the correct qualifier for a top-level IBOutlet on OS X (iOS is another story). However, to create a proper weak reference that zeroes on deallocation requires cooperation from the Objective C runtime. Classes that override retain or release break this support and so you can't create a weak reference to them. UIWindow is one such class.

That's why the template uses 'assign'. Perhaps it should really use the synonym 'unsafe_unretained' if ARC is enabled. In either case you have a simple weak reference that is not zeroed.

抱猫软卧 2024-12-18 22:40:45

Mike Ash 的博客与一些 Cocoa 类讨论了这个问题。

在页面的中间部分查找它: 周五问答 ARC。查找/搜索以“ARC 的清零弱引用实现...”开头的文本

问题是某些类不处理 __weak 带来的清零弱引用。解决方案是使用普通 ARC 模板提供的分配

好吧,回答第二个问题,即使Apple的模板在使用ARC时也使用分配窗口。所以你现在可能是安全的。但您的里程将来可能会有所不同。

Mike Ash's blog discusses the issue with some Cocoa classes.

Look for it in the middle part of the page: Friday Q&A ARC. Look/Search for the text that starts with "ARC's implementation of zeroing weak references..."

The problem is that some classes don't handle the zeroing weak references that __weak brings. The solution is to go with what the normal ARC templates provide assign.

Well, to answer the second question, even Apple's templates use assign for window when using ARC. So you may be safe for now. But your mileage may vary in the future.

眼睛会笑 2024-12-18 22:40:45

Mike Ash 对什么有很好的解释这里出了问题(搜索“ARC的实现”)。其要点是 NSWindow 类特别不支持弱引用:显然是因为它依赖于用自己的实现重写保留和释放。

我预计遗留的 Cocoa 类中还散布着更多这样的问题,而且这些问题似乎还没有被记录下来——相反,您可以通过运行时错误来发现。 (我预计这在某些时候也会成为编译器警告。)

Mike Ash has a very good explanation of what's going wrong here (search for "ARC's implementation"). The gist of it is that the NSWindow class specifically does not support weak referencing: apparently because it relies on overriding retain and release with its own implementations.

I expect there's a few more such gotchas scattered through the legacy Cocoa classes, and these don't appear to be documented yet - instead, you find out through a runtime error. (I expect this will become a compiler warning as well at some point.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文