iOS开发18-iOS 诸葛亮的锦囊妙计--Block的使用
代码下载(Xcode7.0.1)有问题请联系博主,邮箱:nathanlee1987@aliyun.com
1、函数和函数指针
//使用typedef给函数指针类型重新起名字
typedef void (*aFunc)();//无参数无返回值
typedef int (*bFunc)(int ,int);//有参数有返回值
//定义一个标准函数4部分:返回值类型 参数列表 函数名 函数体
//无返回值无参数
void sayHi()
{
NSLog(@"Hello world!");
}
//有返回值有参数
int add(int a,int b)
{
return (a+b);
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
//如何来调用标准函数
//第一种:使用函数名
// sayHi();
// NSLog(@"%d",add(1,2));
/* 运行结果
2015-11-05 19:49:15.003 [3128:367106] Hello world!
2015-11-05 19:49:15.004 [3128:367106] 3
Program ended with exit code: 0
*/
//第二种:使用函数指针
//函数有类型:返回值类型,参数列表
//函数指针类型必须与指向的函数类型相同
/*
void (*af)();//定义函数指针-这个函数指针指向一个无参数无返回值的函数
//将函数地址赋值给函数指针
af=sayHi;//函数名就代表函数的地址
af();//执行函数
int (*bf)(int ,int);//定义函数指针-这个函数指针指向一个有参数有返回值的函数
bf=add;//将函数地址赋值给函数指针//函数名就代表函数的地址
NSLog(@"bf(2,3)=%d",bf(2,3));//执行函数
*/
/*运行结果:
2015-11-05 19:50:03.788 OC_6_1[3136:367805] Hello world!
2015-11-05 19:50:03.789 OC_6_1[3136:367805] bf(2,3)=5
Program ended with exit code: 0
*/
/*
//使用typedef给函数指针类型重新起名字--这样比较方便,不容易出错
aFunc afunc=sayHi;
bFunc bfunc=add;
afunc();
NSLog(@"bfunc(2,9)=%d",bfunc(2,9));
*/
/*运行结果:
2015-11-05 19:50:43.255 [3150:368207] Hello world!
2015-11-05 19:50:43.256 [3150:368207] bfunc(2,9)=11
Program ended with exit code: 0
*/
}
return 0;
}
2、block
Block的本质是匿名函数。拖字符^,block的标志。
定义Block三部分:返回值类型、参数列表、block实现体{}。
定义block的语法
^ 返回值类型(参数列表:参数类型,参数名)
{
//实现部分
//类似于函数体
//如果block有返回值,需要return语句
};
block是匿名函数,不能像函数一样通过函数名来调用。
block可以定义类似函数指针的block变量,通过block变量调用定义的block。
block定义完成之后,必须调用,才能完成功能。 一般使用block,要使用block变量。
通过返回值和参数确定block类型 从而确定block变量的类型。
block可以自动推算出返回值类型, block的定义部分,返回值类型可以省略不写,如果无参数则参数也可以省略不写。
//1.无参数 无返回值
void (^b1)()=^{
NSLog(@"Hi");
};
//2.有参数 无返回值
void(^b2)(NSString *) =^void(NSString*s){
NSLog(@"%@",s);
};
//3.有返回值 无参数
NSString *(^b3)()=^(){
return @"123";
};
//4.有返回值 有参数
NSString *(^b4)(NSString*,NSString*)=^(NSString* s1 ,NSString* s2){
return s1;
};
//使用typedef给block类型重定义
//返回两个整型数的最大值
typedef int(^maxBlock)(int,int);
//传入两个字符串,返回拼接后的字符串
typedef NSString *(^strAppendBlock)(NSString* ,NSString*);
//使用typedef定义
/*
maxBlock block1=^int (int a,int b){
return (a>=b?a:b);
};
NSLog(@"%d",block1(1,2));
*/
/*
strAppendBlock block2=^NSString*(NSString * s1,NSString * s2){
return [s1 stringByAppendingString:s2];
};
NSLog(@"%@",block2(@"123",@"abc"));
*/
3、block与变量
1.block内部定义的局部变量:可以读取、修改
2.block外部定义的局部变量:只能读取,不能修改(只是拷贝了一份值,无法修改,没有操作到它的存储空间)
3.使用__block修饰的外部定义的局部变量:可以读取、修改
4.静态变量:可以读取、修改
5.全局变量:可以读取、修改
【全局指的是作用域,静态指的是存储区域】
4、block防止循环引用
__block typeof(self) weakSelf = self;
__weak typeof(self) weakSelf=self;
5、block传值
NextViewController.h
#import <UIKit/UIKit.h>
typedef void(^passValueBlock) (NSString * s);
@interface NextViewController : UIViewController
@property(nonatomic,strong) UITextField *utf;
@property(nonatomic,copy)passValueBlock pb;
@end
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.pb(self.utf.text);
[self.navigationController popToRootViewControllerAnimated:YES];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NextViewController * nextVC = [[NextViewController alloc]init];
nextVC.pb = ^(NSString *s){
self.utf.text=s;
};
[self.navigationController pushViewController:nextVC animated:YES];
}
运行效果:绿色页面传值给橘黄色页面
6、block在异步操作中的应用
当我们做一些网络请求的时候,结果无法即时返回,这时候,需要用Block回调一下,在网络请求结束的时候,做一些我们计划好的事情,这里使用Block非常方便。
比通知中心和代理方法简捷方便。
+(instancetype)shareMusicDataHandleWithFinishBlock:(finishBlock)finishblock{
if (musicHandle==nil) {
musicHandle =[[MusicDataHandle alloc]init];
musicHandle.musicArray =[NSMutableArray array];
//开辟一个子线程
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[musicHandle getMusicData];
finishblock();
});//开辟一个子线程
}
return musicHandle;
}
有问题请联系博主,邮箱:nathanlee1987@aliyun.com
著作权声明:本文由http://my.csdn.net/Nathan1987_原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢