Xcode升级到4.5后应用程序崩溃。 将保留的对象分配给unsafe_unretainedvariables

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

 @property (nonatomic, assign) dispatch_queue_t queue; 

然后在我的init方法中,我这样做:

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

在Xcode 4.4.1中,它工作并没有造成任何问题(应用程序在appstore中testing+)。 现在,我升级到Xcode 4.5后,应用程序崩溃与EXC_BAD_ACCESS和Xcode给我一个警告,该行说:

将保留对象分配给unsafe_unretainedvariables; 对象将在分配后被释放

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 

希望有人认为它有用

首先,如果您的目标平台是5+,那么我强烈build议使用iOS 5 SDK进行构build。 build立一个更高版本的SDK并设置“目标”可以工作,但有很多问题(其中最重要的是你没有编译器帮助你find使用不支持的方法的地方)。 所以答案1:你需要iOS 5,build立对iOS 5,这不应该。

在iOS 6中, dispatch_queue_t是一个ObjC对象。 这是一个很大的改进。 这意味着您可以为其创buildstrong属性,而ARC将负责其余部分。 如果你的目标iOS 6,这应该只是工作。

如果您需要为iOS 5和iOS 6构build相同的代码,那么您需要知道哪些是您需要时可以放入内存pipe理的内容,如果不需要,可以将其保留。 正确的testing使用#if OS_OBJECT_USE_OBJC 。 请记住,这是编译时检查。 它只适用于处理您要针对不同SDK编写的代码。 对于一个给定的SDK,行为将是一种或另一种方式。

关于“unsafe_unretained”与“assign”混淆:在这种情况下它们是一样的。 “分配”仅适用于非对象。 “unsafe_unretained”是“assign”在应用于对象时转换的内容。 而在iOS6中, dispatch_queue_t是一个对象。

还有一个解决方法,特别是如果你真的想在使用iOS 6 SDK的时候保留旧的内存pipe理代码的话。 您可以将-DOS_OBJECT_USE_OBJC=0传递给编译器。 这将select退出新模式。 但我会推荐这是最后的手段。 有关详细信息,请参阅SDK中的os/object.h 。 (Cmd-Shift-O,object.h)