关于iphone:Xcode升级到4.5后App崩溃了。

App crashes after Xcode upgrade to 4.5. Assigning retained object to unsafe_unretained variable

在我的班级里,我有一个这样宣布的dispatch_queue_t财产:

1
@property (nonatomic, assign) dispatch_queue_t queue;

然后在初始化方法中,我会:

1
2
3
4
5
6
7
8
9
- (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中的app test+)。现在,在我升级到xcode 4.5之后,应用程序崩溃,xcode会在该行警告我说:

将保留的对象分配给不安全的未保留变量;对象将在分配后释放

苹果将Xcode4.5中的编译器从llvm 4.0更新到llvm4.1,但我不知道为什么我的代码现在会崩溃。

我跨过代码,崩溃就发生在那行之后。你知道什么地方可能有问题,我该怎么解决吗?

解决方案:

我设法让它和两个SDK一起工作。我只是加了一句:

1
2
3
4
5
#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中,EDCOX1×0是一个Objc对象。这是一个很大的进步。这意味着您可以为它创建strong属性,其余的由arc负责。如果你的目标是iOS 6,这应该是可行的。

如果您需要为iOS 5和iOS 6构建相同的代码,那么您需要知道哪一个代码,以便在需要时放入内存管理,而不需要时将其删除。要使用的正确测试是#if OS_OBJECT_USE_OBJC。记住,这是编译时检查。它只适用于处理您想要针对不同的SDK编写的代码。对于一个给定的SDK,行为将以一种方式或另一种方式唤醒。

关于"不安全"与"分配"的混淆:在这种情况下,它们是相同的。分配"仅适用于非对象"。"不安全"是应用于对象时转换为"分配"的内容。在ios6中,dispatch_queue_t是一个对象。

还有一个解决方法,特别是在使用iOS6sdk构建时,如果您确实希望保留旧的内存管理代码。您可以将-DOS_OBJECT_USE_OBJC=0传递给编译器。这将退出新型号。但我建议这是最后的办法。有关详细信息,请参见SDK中的os/object.h。(命令-shift-o,对象.h)