使用块指针作为成员变量时,iOS 中与 ARC 相关的崩溃
谁能帮忙解决 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。
Can anyone please help with ARC and memory-related crashes?
I have class LTRequest
with a member variable that stores a block pointer:
typedef void (^APICallOKBlock)(id);
@interface LTRequest : NSObject
@property (nonatomic, strong) APICallOKBlock okCB;
@end
The code to initialize that variable:
-(void)addOKBlock:(APICallOKBlock)okBlock
{
self.okCB = okBlock;
}
I call the block in case of success:
-(void)apiCallCompletedWithResult:(id)result
{
if(self.okCB != nil)
{
self.okCB(result);
}
}
For reference, the block looks something like this:
APICallOKBlock okBlock = ^(id result)
{
[self handleAPICallCompleted:result];
};
It calls a function defined in the object that scheduled the api call, however that part is not important. Important is what happens when apiCallCompletedWithResult
is called after the api call has been successful. And what happens is that the block gets called but the app crashes shortly afterwards when the request object LTRequest
gets deallocated (SomeAppName is our application):
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
I tried to use unsafe_unretained
instead of strong
to store the block in the LTRequest
object:
@property (nonatomic, unsafe_unretained) APICallOKBlock okCB;
In that case the crash happens exactly in the line with the 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 }
Am I using the pointer to a block properly and how should I call it to not cause any crashes?
Some info: I am using iOS SDK 5.0, deployment target is 4.0, device iPhone, and ARC is enabled for the whole project.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您希望该属性是
copy
而不是retain
:You want the property to be
copy
rather thanretain
:将块的实例保存到类实例时,您需要复制该块。
You need to copy the block when saving its instance to the class instance.