Xcode升级到4.5后应用程序崩溃.将保留对象分配给unsafe_unretained变量

Raf*_*fAl 6 iphone objective-c ios

在我的课堂上,我有一个dispatch_queue_t声明如下的属性:

@property (nonatomic, assign) dispatch_queue_t queue;
Run Code Online (Sandbox Code Playgroud)

然后在我的init方法中我做:

- (id)initWithServerUrls: (NSString*)serverUrls
{
    if (self = [super init])
    {
        _queue = dispatch_queue_create("com.xxx.my_send_queue", DISPATCH_QUEUE_SERIAL);
    }

    return self;
}
Run Code Online (Sandbox Code Playgroud)

在Xcode 4.4.1中它起作用并且没有引起任何问题(在appstore中测试的应用程序+).现在,在我升级到Xcode 4.5后,应用程序崩溃了EXC_BAD_ACCESS,Xcode在该行上发出警告说:

将保留对象分配给unsafe_unretained变量; 对象将在分配后释放

Apple将Xcode 4.5中的编译器从LLVM 4.0更新为LLVM 4.1,但我不知道为什么我的代码现在崩溃了.

我逐步完成了代码,崩溃发生在该行之后.你有任何想法可能是错的,我该如何解决?

解:

我设法让它与两个SDK一起工作.我刚补充说:

#if OS_OBJECT_USE_OBJC
@property (nonatomic, strong) dispatch_queue_t queue; // this is for Xcode 4.5 with LLVM 4.1 and iOS 6 SDK
#else
@property (nonatomic, assign) dispatch_queue_t queue; // this is for older Xcodes with older SDKs
#endif
Run Code Online (Sandbox Code Playgroud)

希望有人发现它有用

Rob*_*ier 13

首先,如果您的目标平台是5+,那么我强烈建议使用iOS 5 SDK构建.使用更高版本的SDK构建并设置"目标"可以工作,但是有很多问题(其中最重要的是你没有编译器帮助找到你使用不支持的方法的地方).所以答案1:你需要iOS 5,针对iOS 5进行构建,这无关紧要.

在iOS 6中,dispatch_queue_t是一个ObjC对象.这是一个很大的进步.这意味着你可以strong为它创建属性,ARC将负责其余的工作.如果你的目标是iOS 6,这应该可行.

如果你需要为iOS 5和iOS 6构建相同的代码,那么你需要知道哪些是什么,以便你可以在需要时将其放入内存管理中,而在不需要时将其保留.要使用的正确测试是#if OS_OBJECT_USE_OBJC.请记住,这是一个编译时检查.它仅适用于处理您要针对不同SDK编写的代码.对于给定的SDK,行为将以某种方式消失.

关于"unsafe_unretained"与"assign"混淆:在这种情况下它们是相同的."assign"仅适用于非对象."unsafe_unretained"是应用于对象时转换为"assign"的内容.在iOS6中,dispatch_queue_t是一个对象.

还有一个解决方法,特别是如果您确实希望在使用iOS 6 SDK构建时保留旧的内存管理代码.您可以传递-DOS_OBJECT_USE_OBJC=0给编译器.这将选择退出新模型.但我会建议这作为最后的手段.有关详细信息,请参阅os/object.hSDK.(Cmd-Shift-O,object.h)

  • 请注意,如果您只是在两个平台上*运行*,那么您应该只为iOS 5构建.如果您需要相同的代码来根据您正在构建的平台进行不同的编译,则只需要这样做.如果你需要替换`@ property`行,只需将它包装在`#if`检查中(如果设置了变量,则使用`copy`.如果未设置变量,则使用`assign`.) (2认同)