在這個大冬天里默默敲著鍵盤,勿噴.今天學習swift過程中,學習到閉包,發現閉包和oc的block中有很多的相同之處,又重新學習了一下並且學習了一些高級點的用法,內容如下:1.block格式說明:(返回類型)(^塊名稱)(參數類型) = ^(參數列表) {代碼實現};//如果沒有參數,等號後面參數列...
在這個大冬天里默默敲著鍵盤,勿噴.今天學習swift過程中,學習到閉包,發現閉包和oc的block中有很多的相同之處,又重新學習了一下並且學習了一些高級點的用法,內容如下:
1.block格式說明:(返回類型)(^塊名稱)(參數類型) = ^(參數列表) {代碼實現};//如果沒有參數,等號後面參數列表的()可以省略 例子:void(^demoBlock)() = ^ {
NSLog(@"demo Block");
};
int(^sumBlock)(int, int) = ^(int x, int y) {
return x + y;
};
2.block中使用的變數將以複製的形式保留,在block中保留block的複製的變數,預設情況下,Block外部的變數,在Block中是只讀的!當使用__block關鍵字後,同樣可以在Block中修改外部變數的數值. 3.可以使用typedef定義一個Block的類型,便於在後續直接使用,如:
typedef double(^MyBlock)(double, double);
MyBlock area = ^(double x, double y) {
return x * y;
};
MyBlock sum = ^(double a, double b) {
return a + b;
};
NSLog(@"%.2f", area(10.0, 20.0));
NSLog(@"%.2f", sum(10.0, 20.0));
4.儘管,typedef可以簡化Block的定義,但在實際開發中並不會頻繁使用typedef關鍵字,這是因為Block具有非常強的靈活性,尤其在以參數傳遞時,使用Block的目的就是為了立即使用 官方的數組遍歷方法聲明如下:- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block;
而如果使用typedef,則需要: (1)typedef void(^EnumerateBlock)(id obj, NSUInteger idx, BOOL *stop); (2)- (void)enumerateObjectsUsingBlock:(EnumerateBlock)block;而最終的結果卻是,除了定義類型之外,EnumerateBlock並沒有其他用處
5.Block可以被當做參數直接傳遞NSArray *array = @[@"張三", @"李四", @"王五", @"趙六"];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"第 %d 項內容是 %@", (int)idx, obj);
if ([@"王五" isEqualToString:obj]) {
*stop = YES;
}
}];
或者:
MyBlock sumBlock = ^(double x, double y) {
return x * y;
};
- (void)add:(int)number withNumber:(int)withNumber sumBlock:(MyBlock) block
{
NSLog(@"執行add:(int)number withNumber:(int)withNumber sumBlock:(void (^)(void))block");
NSLog(@"hahaha--4和2相乘等於:%f",block(number,withNumber));
}
[self add:4 withNumber:2 sumBlock:sumBlock];
6.既然Block是一種數據類型,那麼可以將Block當做比較特殊的對象,添加到數組
#pragma mark 定義並添加到數組
@property (nonatomic, strong) NSMutableArray *myBlocks;
int(^sum)(int, int) = ^(int x, int y) {
return [self sum:x y:y];
};
[self.myBlocks addObject:sum];
int(^area)(int, int) = ^(int x, int y) {
return [self area:x y:y];
};
[self.myBlocks addObject:area];
#pragma mark 調用保存在數組中的Block
int(^func)(int, int) = self.myBlocks[index];
return func(x, y);
7.解除迴圈引用
局部變數預設都是強引用的,離開其所在的作用域之後就會被釋放 使用__weak關鍵字,可以將局部變數聲明為弱引用__weak DemoObj *weakSelf = self;
n在Block中引用weakSelf,則Block不會再對self做強引用int(^sum)(int, int) = ^(int x, int y) {
return [weakSelf sum:x y:y];
};
8.今天重點,參考AFN的框架,block根據函數判斷正確與否調用success或者failure函數參數,並傳入參數.如下:
//由於主要還是用來判斷success和failure函數,所以看著不舒服的同學可以自行腦補,將success換成add,將failure換成multiplied
- (void)viewDidLoad {
[super viewDidLoad];
self.isbool = true;//當isbool等於true的時候就相加,否則就相乘
[self setCompletionBlockWithSuccess:^(int x,int y) {
NSLog(@"相加等於:%d",x+y);
NSLog(@"success");
} failure:^(int x,int y) {
NSLog(@"相乘等於:%d",x*y);
NSLog(@"failure");
}];
}
- (void)setCompletionBlock:(void (^)(void))block {
block();
NSLog(@"setCompletionBlock number2:%d number3:%d",self.number2,self.number3);
}
- (void)setCompletionBlockWithSuccess:(void (^)(int x,int y))success
failure:(void (^)(int x,int y))failure
{
self.completionBlock = ^{
self.number2 = 10;
self.number3 = 20;
if (self.isbool == true) {//判斷傳入哪個參數,執行success還是failure
NSLog(@"開始相加");
success(self.number2,self.number3);//參數傳入setCompletionBlockWithSuccess
}else{
NSLog(@"開始相乘");
failure(self.number2,self.number3);//參數傳入setCompletionBlockWithSuccess
}
};
}