新浪微博:东门兜
关于block的一些问题:
1、TASMVwCtrlPeopleAlbum 类下有个方法:onTakeAlbumAction,里面有段代码:
AGImagePickerController *imagePickerController = [[AGImagePickerController alloc] init];
__block TASMVwCtrlPeopleAlbum *wself = self;
imagePickerController.didFailBlock = ^(NSError *error) {
if (!error) {
[wself.selectedPhotos removeAllObjects];
[imagePickerController dismissViewControllerAnimatedEx:YES completion:nil];
}
}
;
观看上面的例子(上面的例子是正确的),MRC下如果不加__block,会造成循环引用。
原因是:(1)imagePickerController是TASMVwCtrlPeopleAlbum类的一个变量。即类引用了该变量。didFailBlock是imagePickerController类的一个变量。而didFailBlock这个block中又引用了self。所以:
TASMVwCtrlPeopleAlbum –> imagePickerController
imagePickerController -> didFailBlock
didFailBlock -> TASMVwCtrlPeopleAlbum
这样就照成循环引用。
(2)或许,有人会问:如果block中不执行if语句的代码不就没事了?
答:该想法是错误的。block在创建的时候,它会扫描block中所有的对象,并将他们retain。无论有没有执行if。
(3)或许,还有人会问:如何知道didFailBlock这个block执行的线程是在主线程?
答:有个名人说:“那就需要你去查查该代码的说明,看它返回时在主线程还是在子线程;一般情况下是在主线程。”
2、某方法中含有这句话:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
RequestResult *request = [GroupRequestNet searchGroup:dwGid keyword:strKeyWord];
self.lastContent = @"";
}
);
观看上面的例子(上面的例子是有危险的),可以发现,在子线程中执行了self操作。
原因是:
(1) 执行了这段代码,block被加入到dispatch_queue中,对block进行拷贝,拷贝过程中,就对block中的对象的retainCount加1(即self的retainCount+1),这就有点危险了。
(2) 比如当前控制器的retainCount原来是1,经过这个block后,当前控制器的retainCount变成了2,所以:当控制器因为diss或其他操作release一次后(即retainCount-1,这时retainCount=1),并且这个block还未运行完的时候,就会导致当block运行完,对block进行释放,释放过程中,就使self的retainCount-1,然后调用了dealloc方法,而这个操作是在子线程中操作,就会出现问题。
3、某方法中含有这句话:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
RequestResult *request = [GroupRequestNet searchGroup:dwGid keyword:strKeyWord];
self.lastContent = @"";
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewControllerEx:searchResultViewController animated:YES];
}
);
}
);
观看上面的例子(上面的例子是正确的)
原因是:
(1) 在第一个block中,在子线程对self进行了retain;在第二个block中,在主线程也对self进行了retain。不必担心。
(2) 控制器的retainCount为3,控制器因为diss或其他操作release一次后(retainCount-1),当block执行完之后进行销毁时,对第一个block进行release,使控制器的(retainCount-1,在子线程操作),当第二个block进行release时,使控制器的retainCount-1,执行dealloc操作(在主线程)OK!
(3)或许有人会问,如果第一个block代码执行途中返回了,没有执行到第二个block,那样会不会有问题?
答:有的,同学。假设在第一个block中有段代码return了,致使没有执行到第二个block,这样就会有问题,可能导致self的释放在子线程中进行,如下例子(下面的例子是有危险的):
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
RequestResult *request = [GroupRequestNet searchGroup:dwGid keyword:strKeyWord];
if(1){
return ;
}
self.lastContent = @"";
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewControllerEx:searchResultViewController animated:YES];
}
);
}
);