- Block 也是一種 Objective-C 對象,可以用于賦值,當做參數傳遞,當做返回值,也可以放入 NSArray 和 NSDictionary 中。
1>. 如果是局部變量,Block是值傳遞
int a = 3;
void (^closure)() = ^{
NSLog(@"a = %d",a);
};
a = 5;
closure(); // a = 3;
2>. 如果是靜態變量,全局變量,__block修飾的變量, Block是指針傳遞
static int a = 3;
void (^closure)() = ^{
NSLog(@"a = %d",a);
};
a = 5;
closure(); // a = 5;
3.1> . 解決循環引用
@property (nonatomic , strong) void (^ failureBlock)();
__weak typeof(self) weakSelf = self;
_failureBlock = ^(){
__strong typeof(weakSelf) strongSelf = weakSelf;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@",strongSelf);
});
};
_failureBlock();
解釋:1. _failureBlock 會對外面所有的‘強指針對象’進行強引用,包括 ‘self’ 對象 , 所以要在 外面用 __weak 聲明一個弱指針類型的 self 供代碼塊里面使用。 2. 代碼塊中為什么要用 “__strong” 在搶引用 一次 “weakSelf” ,是為了防止在執行 “dispatch_after” 時 weakSelf 變成 nil.
3.2>
__weak __typeof__(self) weakSelf = self;
NSBlockOperation *op = [[NSBlockOperation alloc] init] ;
[ op addExecutionBlock:^ {
__strong __typeof__(self) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doMoreThing];}
];
[someOperationQueue addOperation:op];
__strong這一句在執行的時候,如果 WeakSelf 還沒有變成 nil,那么就會 retain self,讓 self 在 block 執行期間不會變為 nil。
這樣上面的 doSomething和 doMoreThing 要么全執行成功,要么全失敗,不會出現一個成功一個失敗,即執行到中間 self變成 nil 的情況。 如果想全部執行成功,可以用block 在引用一次。
總結 :Block 會對里面所有的外部的所有 ’強指針’ 進行全部‘強引用’。
blcok作為返回值的使用情況
參考下masonry框架的demo;
[blueView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.and.height.equalTo(redView);//使寬高等于 redView
}];
make.width.and.height.equalTo(redView);
“equalTo” 的返回值就是 “Block”,然后在調用block,傳入參數redView. 想必這種鏈式語法大家都很喜歡。下面是一個簡單的小例子。
Calculate.h
@interface Calculate : NSObject
@property (nonatomic, readonly) double result;
-(Calculate * (^)(double number))plus;
@end
Calculate.m
@interface Calculate ()
@property (nonatomic, readwrite) double result;
@end
@implementation Calculate
- (Calculate * (^)(double number))plus{
return ^(double num){
_result += num;
return self;
};
}
@end
調用的時候:
Calculate *cal = [Calculate new];
double res = cal.plus(1).plus(2).plus(3).result;
NSLog(@"%f",res); // 6.000000
可以一直用點語法一直plus,最后可以直接調用result得到我們的計算結果。
最后看一下怎么快速調用block,學過前端的同事感覺是不是很熟悉。
(^(UIColor * backgroundColor){
self.view.backgroundColor = backgroundColor;
})([UIColor redColor]);
那么上面 "3.2>"的要想全部成功就可以這么寫。
__weak __typeof__(self) weakSelf = self;
NSBlockOperation *op = [[NSBlockOperation alloc] init] ;
[ op addExecutionBlock:^ {
__strong __typeof__(self) strongSelf = weakSelf;
(^{
[strongSelf doSomething];
[strongSelf doMoreThing];
})();
}];
[someOperationQueue addOperation:op];
這樣就會自動強引用“ strongSelf”。