通过这个类我发送http请求:
@interface AsyncRequest()
@property(strong,nonatomic)NSURLRequest* murlRequest;
@property(copy) OnCompleted onCompletedBlock;
@end
@implementation AsyncRequest
//Async Request object initialization
-(instancetype)initWithUrl:(NSString*)urlRequest onCompletedBlock:(OnCompleted) onCompeletedBlock
{
self = [super init];
if(self)
{
//blocks
NSURL* url = [NSURL URLWithString:[NSStringstringWithFormat:@"%@%@",SERVER_URL,urlRequest]];
self.onCompletedBlock = onCompeletedBlock;
self.murlRequest = [NSURLRequest requestWithURL:url];
}
return self;
}
//call this function to execute the specified request
-(void)ExecuteRequest
{
AsyncRequest * __weak weakself = self;
//localVariable is used by value, a strong reference is made to localVariable in the block
NSURLRequest *urlRequest = self.murlRequest;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^(void){
NSURLResponse *response = nil;
NSError *error = nil;
NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
//main ui
dispatch_async(dispatch_get_main_queue(),^{
weakself.onCompletedBlock(data);
});
}
@end
所以我声明onComplete块并在initWithUrlFunction
初始化它们然后我用weakself来运行它。
但问题是我在weakself.onCompletedBlock(data) ->
线程1:EXC_BAD_ACCESS(代码= 2,地址=位于0xC)
问题是什么?
答案 0 :(得分:3)
您需要先将weakself.onCompletedBlock
分配给强大的var,然后在调用之前测试它不是nil
。
在调用之前,你需要测试块不是nil
,除非你能保证它不能为零。或者您的应用程序崩溃时出现错误的错误消息。与nil
对象上的invoke方法完全不同,调用nil
块会导致取消引用无效的内存地址。
block()
将编译为block->someFunction(block->someStruct)
,如果block
为NULL
/ 0
,则会导致C ++样式崩溃。
您不想多次访问__weak
变量。您必须将其分配给__strong
变量,然后才能访问它。否则可能会意外释放,因为它没有被保留。
__weak Foo *obj = // something
[obj dowork]; // obj may be valid value at this point
[obj dootherwork]; // obj may be nil here even previous call success
id foo = obj->somevar; // may crash with dereference invalid memory address
你需要做的是
__weak Foo *obj = // something
Foo *strongObj = obj;
if (strongObj) { // not always required
// you know strongObj is retained and will not be released until it go out of scope
// so you can access strongObj safely without surprise
}
答案 1 :(得分:0)
这里weakSelf
模式不合适。它用于避免强引用周期,这不是风险。在这种情况下,您只希望此dispatch_async
块保留其组成对象,直到异步块执行,因此只需使用self
。
顺便说一下,如果可能在没有提供完成块的情况下调用此方法,则应确保它不是nil
,因此:
dispatch_async(dispatch_get_main_queue(),^{
if (self.onCompletedBlock) {
self.onCompletedBlock(data);
}
});