一 代码块的语法
代码块的书写和C语言函数的语法格式有点像,例如下面求和函数分别用C 语言和代码块来实现:
2.使用代码块"指针"的方式来实现,例如:
void (^succeedBlock)(void) = ^
{
NSLog(@"do something succeed thing");
};
void (^failedBlock)(void) = ^
{
NSLog(@"do some failed thing");
};
NSInteger localInteger = 10;
NSLog(@"local integer = %ld", (long)localInteger);
int insideInteger = 10;
++insideInteger;
//outsideInteger = 5; //这样直接写会报错误 提示outsideInteger没有加__block
NSLog(@"ousideInteger=%d insideInteger=%d",outsideInteger,insideInteger);
}failedBlock:^{
NSLog(@"inline failed block!");
}];
NSLog(@"self = %@", self);
NSlog(@"self = %@",self);
}failedBlock:^{
NSLog(@"inline failed block!");
}];
/*************** Definition of internal block object ***************/
/*************** Definition of internal block object ***************/
@end
代码块的书写和C语言函数的语法格式有点像,例如下面求和函数分别用C 语言和代码块来实现:
int add(int a,int b)
{
return a+b;
}
int (^add)(int a,int b) = ^(int a,int b)
{
return a +b;
};
{
return a +b;
};
注意:a.代码块最后的大括号后面一定要加分号。
b.与c语言的函数签名不同的是,代码块的名字需要用'^'和括号。
c. 代码块的签名部分和实现部分需要用'=^(参数列表)'来连接。
除次之外代码块还可以将签名和实现部分分开来实现,例如:
void (^PrintInfo)(NSString *info);
PrintInfo = ^(NSString *info)
{
NSLog(@"%@",info);
};
PrintInfo = ^(NSString *info)
{
NSLog(@"%@",info);
};
代码块也可以看作是函数的指针,差别是用^代替了*.
二 代码块的调用方式
1.直接调用,例如,对于刚才定义的PrintInfo代码块
PrintInfo(
@"Hello World"
);
2.使用代码块"指针"的方式来实现,例如:
typedef void (^Print) (NSString *info);
void (^PrintName) (NSString * name) = ^(NSString * name)
{
NSLog(@"MyName:%@",name);
};
Print myBlock = PrintName;
myBlock(@"Hello");
void (^PrintCountry)(NSString * Country)= ^(NSString *Country)
{
NSLog(@"MyCountry:%@",Country);
};
myBlock= PrintCountry;
myBlock(@"China");
{
NSLog(@"MyName:%@",name);
};
Print myBlock = PrintName;
myBlock(@"Hello");
void (^PrintCountry)(NSString * Country)= ^(NSString *Country)
{
NSLog(@"MyCountry:%@",Country);
};
myBlock= PrintCountry;
myBlock(@"China");
注: 在一个block的内部可以调用另外一个block
/*************** Definition of first block object ***************/
NSString *(^trimString)(NSString *) = ^(NSString *inputString)
{
NSString *result = [inputString stringByTrimmingCharactersInSet:
NSString *result = [inputString stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceCharacterSet]];
return result;
};
/*************** Definition of second block object ***************/
return result;
};
/*************** Definition of second block object ***************/
NSString *(^trimWithOtherBlock)(NSString *) = ^(NSString *inputString)
{
return trimString(inputString);
return trimString(inputString);
}
3.使用方法举例
代码块的作用主要是用来做回调函数来使用的,它可以代替IOS SDK中的代理方法。使用代码块比用代理
方法的效率更高。
a.首先定义两个代码块指针
typedef void (^SucceedBlock)(void); //访问服务器成功的时候
typedef void (^FailedBlock )(void); //访问服务器失败的时候
b.定义访问服务器方法
- (void) getDataFromServer:(NSString*) URL succeedBlock:(SucceedBlock) succeed
typedef void (^FailedBlock )(void); //访问服务器失败的时候
b.定义访问服务器方法
- (void) getDataFromServer:(NSString*) URL succeedBlock:(SucceedBlock) succeed
failedBlock:(FailedBlock) fail
{
{
//模拟调用成功和失败
if ([URL isEqualToString:@"YES"])
{
succeed();
}
else
{
fail();
}
}
c.调用上面的方法
if ([URL isEqualToString:@"YES"])
{
succeed();
}
else
{
fail();
}
}
c.调用上面的方法
void (^succeedBlock)(void) = ^
{
NSLog(@"do something succeed thing");
};
void (^failedBlock)(void) = ^
{
NSLog(@"do some failed thing");
};
采用独立代码块的方式实现函数的调用
[self getDataFromServer:@"YES" succeedBlock:succeedBlock failedBlock:failedBlock];
也可以在调用的时候来定义代码块(内联的方式实现代码块的调用)
[ self getDataFromServer:@"NO" succeedBlock:^{
NSLog(@"inline succeed block!");
}failedBlock:^{
NSLog(@"inline failed block!");
{
block(name);
{
[ self getDataFromServer:@"NO" succeedBlock:^{
NSLog(@"inline succeed block!");
}failedBlock:^{
NSLog(@"inline failed block!");
}
];
d.直接用代码块作参数
-(void) testBlock:(NSString*)name completionBlock:(void (^)(NSString* addr)) block{
block(name);
}
[self testBlock:@"zhangzhe" completionBlock:^(NSString *addr){
NSLog(@"addr:%@",addr);
}];
四 代码块中变量访问
a.对于独立代码块,内部定义的局部变量的使用方式和普通的objective-c函数是相同的,可以进行读写
void (^independentBlockObject)(void) = ^(void)
{NSInteger localInteger = 10;
NSLog(@"local integer = %ld", (long)localInteger);
lojalitetger = 20;
NSLog(@"local integer = %ld", (long)localInteger);
};
NSLog(@"local integer = %ld", (long)localInteger);
};
localInteger是可以被读写的
b.对于内联方式定义的代码块,局部变量不仅包括在代码块内部定义的变量,而且还包含在实现代码块
函数内部定义的变量。对于前一部分变量是可读写的,对于后一部分变量是只读的。例如:
- (void)viewDidLoad
{
int outsideInteger = 10;
[self getDataFromServer:@"NO" succeedBlock:^{int insideInteger = 10;
++insideInteger;
//outsideInteger = 5; //这样直接写会报错误 提示outsideInteger没有加__block
NSLog(@"ousideInteger=%d insideInteger=%d",outsideInteger,insideInteger);
}failedBlock:^{
NSLog(@"inline failed block!");
}];
}
所以对于代码块外定义的局部变量是只读的,要想可以读写需要在改变量前面加两个下划线+block
__block
int outsideInteger = 10;
c.对于selfl变量的访问,如果是在独立代码块不能直接访问self变量,要访问可以将其作为代码块参数传入,对于内联点名块,只要在实现该代码块的函数可以访问的话,在代码块内部就可以直接访问。
void (^correctBlockObject)(id) = ^(id self)
{NSLog(@"self = %@", self);
};
- (void)viewDidLoad
{
[self getDataFromServer:@"NO" succeedBlock:^{NSlog(@"self = %@",self);
}failedBlock:^{
NSLog(@"inline failed block!");
}];
}
d.对于使用 @property定义的属性变量的访问,如果内联代码块可以使用点号的方式访问,也可以使用
方括号的方式来访问,但是对于独立代码块的话只能使用后者来访问。
@interface GASSViewController : UIViewController
@property(nonatomic,strong) NSString *name;
@end
对于独立代码块
void (^correctBlockObject)(id) = ^(id self)
{
NSLog(@"self = %@", self);
/* Should use setter method instead of this */
self.name = @"Block Objects"; /* Compile-time Error */
/* Should use getter method instead of this */
NSLog(@"self.name = %@",self.name); /* Compile-time Error */
};
对于内联代码块
/* Should use setter method instead of this */
self.name = @"Block Objects"; /* Compile-time Error */
/* Should use getter method instead of this */
NSLog(@"self.name = %@",self.name); /* Compile-time Error */
};
[self getDataFromServer:@"NO" succeedBlock:^{
NSLog(@"self.name = %@",self.name);
}failedBlock:^{
NSLog(@"inline failed block!");
NSLog(@"self.name = %@",self.name);
}failedBlock:^{
NSLog(@"inline failed block!");
}];
e.对于代码块外的变量,代码块会拷贝到自己的一个结构体内(相当于深拷贝),需要注意的是这个深拷贝是在定义代码块的时候进行的,而不是你调用的时候。
typedef void (^BlockWithNoParams)(void);
- (void) scopeTest
{
NSUInteger integerValue = 10;/*************** Definition of internal block object ***************/
BlockWithNoParams myBlock = ^{
NSLog(@"Integer value inside the block = %lu", (unsigned long)integerValue);
};
/*************** End definition of internal block object ***************/
integerValue = 20;
/* Call the block here after changing the value of the integerValue variable */
myBlock();
NSLog(@"Integer value outside the block = %lu", (unsigned long)integerValue);
}
NSLog(@"Integer value inside the block = %lu", (unsigned long)integerValue);
};
/*************** End definition of internal block object ***************/
integerValue = 20;
/* Call the block here after changing the value of the integerValue variable */
myBlock();
NSLog(@"Integer value outside the block = %lu", (unsigned long)integerValue);
}
输出的结果:
Integer value inside the block = 10
Integer value outside the block = 20
避免这种情况
- (
void) scopeTest
{
__block NSUInteger integerValue = 10;/*************** Definition of internal block object ***************/
BlockWithNoParams myBlock = ^{
NSLog(@"Integer value inside the block = %lu", (unsigned long)integerValue);
};
/*************** End definition of internal block object ***************/
integerValue = 20;
/* Call the block here after changing the value of the integerValue variable */
myBlock();
NSLog(@"Integer value outside the block = %lu", (unsigned long)integerValue);
NSLog(@"Integer value inside the block = %lu", (unsigned long)integerValue);
};
/*************** End definition of internal block object ***************/
integerValue = 20;
/* Call the block here after changing the value of the integerValue variable */
myBlock();
NSLog(@"Integer value outside the block = %lu", (unsigned long)integerValue);
}
输出的结果:
Integer value inside the block = 20
Integer value outside the block = 20
d.对于类中的实例成员来说,在代码块中可以直接访问是可以读写的,不用写__block
@interface GASSViewController ()
@property(nonatomic,strong) NSArray *testArr;@end
@implementation GASSViewController
@synthesize testArr = _testArr;
@synthesize testArr = _testArr;
void (^independentBlockObject)(void) = ^(void)
{
self.testArr = @[@"ONE",@"TWO"];
};
{
self.testArr = @[@"ONE",@"TWO"];
};
independentBlockObject();