新浪微博:东门兜
关于 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];
- });
- });
就爱阅读 www.92to.com 网友整理上传, 为您提供最全的知识大全, 期待您的分享,转载请注明出处。
来源: