在我的类(class)中,我有一个 dispatch_queue_t
属性声明如下:
@property (nonatomic, assign) dispatch_queue_t queue;
然后在我的初始化方法中:
- (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 中它工作并且没有引起任何问题(应用程序在应用程序商店中测试+)。 现在,在我升级到 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
希望有人觉得有用
最佳答案
首先,如果您的目标平台是 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”的混淆:在这种情况下它们是同一回事。 “分配”仅适用于非对象。 “unsafe_unretained”是“assign”应用于对象时转换成的内容。而在 iOS6 中,dispatch_queue_t
是一个对象。
还有一个解决方法,特别是如果您确实想在使用 iOS 6 SDK 构建时保留旧的内存管理代码。您可以将 -DOS_OBJECT_USE_OBJC=0
传递给编译器。这将选择退出新模型。但我建议将此作为最后的手段。具体参见SDK中的os/object.h
。 (Cmd-Shift-O, object.h)
关于iphone - Xcode 升级到 4.5 后应用程序崩溃。将保留的对象分配给 unsafe_unretained 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12511976/