我看过不少文章关于在dispatch_async的block里面使用_weak self, 可是让我疑惑的是,如下代码是否须要必须使用_weak self, 由于我也看到了不少观点说,在有些状况下不须要使用__weak self.objective-c
self.myQueue = dispatch_queue_create("com.biview.core_data", NULL);
dispatch_async(self.myQueue, ^(void){
if(!self.var1){
self.var1 =
}
dispatch_async(dispatch_get_main_queue(), ^(void){
if([self.var2 superview]) {
[self.var2 removeFromSuperview];
}
[self.Label setText:text];
});
});复制代码
针对上面的问题,咱们假设:self是指向UIViewController的对象指针。
考虑如下几点:iview
在上面的例子中,self是在主线程的队列中,没必要担忧有任何bug产生。异步
当在dispatch的异步队列的block中捕获到self时,self会被执行retained操做,当block执行完毕后self执行released操做。
这意味着:当block执行完毕后,self的生命周期才会结束。上例中的第二个block是在主线程的队列中,它保证了self一直存活着当这个block被执行的时候。
在程序中存在潜在危险的操做是:延长 self 的生命周期。async
若是你明确的不但愿延长UIViewController对象的生命周期,而是当block被执行的时候去检查UIViewController对象究竟是否存在,你可使用 _weak self. 须要注意的是block最后都会被执行,无论UIViewController是否存活仍是已经被释放了。fetch
若是你但愿若是UIViewController已经被释放了,那么block不作任何事情,能够写成 _weak self.atom
MyController * _weak weakSelf = self;
dispatch_async(queue, ^{
MyController *strongSelf = weakSelf;
if(strongSelf){
...
}else {
// self has been deallocted in the meantime.
}
});复制代码
不能在非主线程中向UIKit对象发送消息。
另外一个细微的错误可能发生在UIKit对象执行方法在非主线程。spa
若是block在异步线程中捕获了一个UIKit对象,可能发生的是:block 是最后一个持有改UIKit的强引用。当block执行完的时候,UIKit对象将被release,由于是UIKit对象的最后一个强引用,全部该UIKit对象将被释放,可是,释放操做发生在block所执行的线程-它不是主线程,全部,风险即将发生,UIKit对象的dealloc方法将被调用(UI 对象应该在主线程中被回收,由于在它们的 dealloc 方法被调用回收的时候,可能会去改变 view 的结构关系,而如咱们所知,这种操做应该放在主线程来进行,见参考二)。线程
避免这个错误:指针
UIViewController *strongUIKitPointer = ...
dispatch_async(non_main_queue), ^{
...//do someting
dispatch(dispatch_get_main_queue(),^{
[strongUIkitPointer self]; //self is a method, too -doing nothing.
});
});复制代码
双向强引用发生在:一个强类型对象A持有一个强类型对象B,而且对象B强引用对象A。“Block”是一个强引用对象。code
人为的双向强引用举例:
typedef void(^my_completion_block_t)(NSArray* result);
@interface UserViewController : UIViewController
@property (nonatomic, copy) my_completion_block_t completion;
@property (nonatomic) NSArray *users;复制代码
on "UserViewController.m"
self.completion = ^(NSArray *users){
self.users = users;
}
[self fetchUsers];复制代码
这是一个典型了强引用循环。UserViewController 有一个Block类型的属性,全部UserViewController对象强引用着block。而block捕获到self的时候执行强引用操做,全部造成了强引用循环。
解决方式:
使用_weak 指针指向self.
UserViewController * _weak weakSelf = self;
self.completion = ^(NSArray *user){
UsersViewController *strongSelf = weakSelf;
if(strongSelf){
strongSelf.users = users;
}else{
// the view controller does not exist anymore.
}
};复制代码
使用block 指针执行self, 执行完毕后将block 指针指向nil.
UsersViewController *__block blockSelf = self;
self.completion=^(NSArayy *users){
self.completion = ^(NSArray *users){
blockSelf.users = users;
blockSelf = nil;
}
}复制代码
--完--