使用块指针作为成员变量时,与iOS相关的崩溃崩溃

时间:2012-01-13 14:32:02

标签: ios memory-management crash block automatic-ref-counting

任何人都可以帮助解决ARC和与内存相关的崩溃问题吗?

我的类LTRequest带有一个存储块指针的成员变量:

typedef void (^APICallOKBlock)(id);

@interface LTRequest : NSObject
@property (nonatomic, strong) APICallOKBlock okCB;
@end

初始化该变量的代码:

-(void)addOKBlock:(APICallOKBlock)okBlock
{
    self.okCB = okBlock;
}

如果成功,我会调用该块:

-(void)apiCallCompletedWithResult:(id)result
{
    if(self.okCB != nil)
    {
        self.okCB(result);
    }
}

作为参考,该块看起来像这样:

APICallOKBlock okBlock = ^(id result)
{
    [self handleAPICallCompleted:result];
};

它调用在调度api调用的对象中定义的函数,但该部分并不重要。重要的是在api调用成功后调用apiCallCompletedWithResult时会发生什么。发生的事情就是调用了块,但是当请求对象LTRequest被释放时,应用程序很快就崩溃了(SomeAppName是我们的应用程序):

Thread 6 name:  Dispatch queue: com.apple.root.low-priority
Thread 6 Crashed:
0   libobjc.A.dylib                 0x300bad9c objc_release + 12
1   libobjc.A.dylib                 0x300c6c00 objc_storeStrong + 24
2   SomeAppName                     0x00055688 -[LTRequest .cxx_destruct] (LTRequest.m:12)
3   libobjc.A.dylib                 0x300bba66 object_cxxDestructFromClass + 50
4   libobjc.A.dylib                 0x300bba2c object_cxxDestruct + 8
5   libobjc.A.dylib                 0x300b99ac objc_destructInstance + 20

我尝试使用unsafe_unretained代替strong将块存储在LTRequest对象中:

@property (nonatomic, unsafe_unretained) APICallOKBlock okCB;

在这种情况下,崩溃恰好发生在if:

的行中
Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x300b9eda objc_retain + 10
1   libobjc.A.dylib                 0x300c6bde objc_retainAutoreleasedReturnValue + 34
2   SomeAppName                     0x00054f90 -[LTRequest apiCallCompletedWithResult:] (LTRequest.m:84)
3   SomeAppName                     0x0002f8aa __29-[LTServerProxy makeAPICall:]_block_invoke_0 (LTServerProxy.m:154)

// file LTRequest.m

line 84    if(self.okCB != nil)
line 85    {
line 86        self.okCB(result);
line 87    }

我是否正确使用了指向块的指针,如何调用它以避免任何崩溃?

一些信息:我使用的是iOS SDK 5.0,部署目标是4.0,设备iPhone和整个项目都启用了ARC。

2 个答案:

答案 0 :(得分:15)

您希望该属性为copy而不是retain

@property (nonatomic, copy) APICallOKBlock okCB;

答案 1 :(得分:2)

将实例保存到类实例时,需要复制块。

-(void)addOKBlock:(APICallOKBlock)okBlock
{
    self.okCB = [okBlock copy];
}