虚位以待(AD)
虚位以待(AD)
首页 > 软件编程 > IOS编程/Objective-C > iOS Blocks 编程(二)

iOS Blocks 编程(二)
类别:IOS编程/Objective-C   作者:码皇   来源:yyh3663477的专栏     点击:

观看上面的例子(上面的例子是正确的),MRC下如果不加__block,会造成循环引用。原因是:(1)imagePickerController是TASMVwCtrlPeopleAlbum类的一个变量。即类引用了该变量。didFailBlock是imagePickerController类的一个变量。而didFailBlock这个block中又引用了self。

新浪微博:东门兜

关于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];
    }
    );
    }
    );
相关热词搜索: