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 |
希望有人发现它有用
- 自我队列。它修好了吗?-添加"自我"。
- 不,还是一样,撞车。还有警告。
- 而不是"分配保留对象",这意味着从分派队列创建(…"to unsafe-untained variable"是指队列。如果@synthetize无法解决(因为它在构造函数上),而不需要以某种方式操作分派队列创建(返回值,您可以发布该对象吗,他返回了什么?
- 当我在调度队列之后放置一个断点时,它会说"class-error:unknownClass"。但我不知道,因为这可能只是一个糟糕的Xcode调试器。
- 不知道了,除非您更改了arc:strong@property(nonatomic,strong)dispatch_queue_t queue的assign to retain;但这也可能意味着在其他部分更改您的代码。
- 把它改成"强大"的应用程序在不同的地方崩溃了,但我不知道在哪里,为什么。我用日志消息更新了原始问题。
- @Matheszabi为什么会有帮助?错误是无关的,请阅读错误消息(您也是,op!)问题是,当您使用复制的属性时,新的编译器会发出代码,引用一个辅助函数(objc_setproperty_nonatomic_copy()),该函数仅在开发系统根中,在设备d本身上找不到,因此动态加载程序无法解决该符号,无法启动应用程序。将设备升级到iOS 6。
- 顺便说一下,分配和不安全的分配是一样的。
- @ H2CO3谢谢!但是我怎样才能让它在iOS 5和iOS 6上运行呢?
- 拉法?斯罗卡,我认为4.1级冲锋不太可能。你可以降级xcode,或者…(填入)
- 问题是,dispatch_queue_t是ios6中的对象,而不是ios5中的对象。下面列出了几个修复方法。没有一个需要降级编译器(尽管我确实建议将SDK降级到您要针对的版本)。
- 在这次讨论中可以找到一些线索:github.com/cocoapods/specs/issues/352
首先,如果您的目标平台是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)
- 谢谢,这澄清了很多!
- 我需要支持两个版本的iOS,所以我将使用您建议的测试。我现在唯一不知道的是,我应该如何替换"@property(nonatomic,copy)customblock completedblock";这样它就不会使iOS6上的应用程序崩溃。有什么解决办法吗?
- 请注意,如果您只是在两个平台上运行,那么应该只为iOS 5构建。您只需要这一点,如果您需要相同的代码来编译不同,这取决于您构建的平台。如果需要更换@property行,只需将其包装在#if检查中(如果设置了变量,则使用copy)。如果未设置变量,则使用assign。