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

标签 iphone objective-c ios

在我的类(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/

相关文章:

ios - 在后台线程上查找backgroundTimeRemaining

iphone - 如何在 Landscape 而不是 Portrait 中显示 UIImagePickerControllerSourceTypeCamera

iphone - iOS 6.0 中的 CADisplayLink 不保留目标

iphone - 获取 UITableView 周围的边框,如 UIActionSheet

iphone - 如果一个方法接受对象并添加到数组中,是否应在必要时检测并释放该对象?

ios - 使用 xmpp 或任何其他框架在 ios 中使用 google 帐户构建聊天应用程序

iphone - UIScrollView - 确定滚动停止的位置

ios - 如何在字符串的每一侧 append 一个空格?

ios - 选择 tableView 单元格时更改单元格上的按钮图像

ios - 为什么 UIButton.titleLabel?.text 在我在 Swift 5 (UIKit) 中更改后总是切换回来?