iOS(闭包)block传值详解
在iOSAPP开发的过程中我们会用到很多需要传值的地方传值的方式也多种多样有:代理传值、通知传值、KVC、KVO、block、单例等。其中block因为其简洁实用规范的代码无疑是大牛们传值的不二选择但对于初学者来说要理解并能运用起初确实有些难以理解以下我将细细的介绍下block
首先我总结了一下block的公式:
- 步骤1.block的声明返回值类型(^block的名字)(参数列表);
- 步骤2.block实现block的名字=^(参数列表)(){};
- 步骤3.block的调用block的名字();
下面是一个简单的block
//声明 void(^blockName)(intnum,NSString*string); //实现 blockName=^(intnum,NSString*string) { NSLog(@"%d,%@",num,string); }; //调用 blockName(520,@"phyone_"); }
由该例可以看出block的代码执行顺序和其他的代码执行顺序不一样它是先执行声明代码然后执行调用代码最后才执行实现代码由此我们利用block的回调性质达到我们传值效果当然这只是在一个页面的一段代码只是说明了它具有传值的作用下面我们来试试多页面之间的block反向传值由于是反向传值所以我们创建两个ViewController(ViewController,Next_ViewController)先由ViewController跳到Next_ViewController里将里面的值反向传给ViewController
以下是代码
ViewController.m里面
-(void)viewDidLoad{ [superviewDidLoad]; self.view.backgroundColor=[UIColorpurpleColor]; UILabel*lable=[[UILabelalloc]initWithFrame:CGRectMake(100,200,200,100)]; lable.backgroundColor=[UIColorbrownColor]; [self.viewaddSubview:lable]; UITapGestureRecognizer*tap=[[UITapGestureRecognizeralloc]initWithTarget:selfaction:@selector(tap)]; [self.viewaddGestureRecognizer:tap]; } -(void)tap { Next_ViewController*NVC=[[Next_ViewControlleralloc]init]; NVC.block=^(NSString*content){ NSLog(@"%@",content); UIButton*button=[[UIButtonalloc]initWithFrame:CGRectMake(100,200,100,100)]; [buttonsetTitle:contentforState:UIControlStateNormal]; button.backgroundColor=[UIColororangeColor]; [self.viewaddSubview:button]; }; [selfpresentViewController:NVCanimated:YEScompletion:nil]; }
Next_ViewController.h里面
//block是分配在栈里面的用copy @property(nonatomic,copy)void(^block)(NSString*content);
Next_ViewController.m里面
{ void(^imageNameBlock_1)(NSString*imageName); void(^lableBlock)(NSString*tontentText); }
-(void)viewDidLoad{ [superviewDidLoad]; self.view.backgroundColor=[UIColororangeColor]; UIButton*button=[UIButtonbuttonWithType:UIButtonTypeCustom]; button.frame=CGRectMake(100,200,100,50); [buttonsetTitle:@"123456"forState:UIControlStateNormal]; button.backgroundColor=[UIColorredColor]; [buttonaddTarget:selfaction:@selector(buttonAction:)forControlEvents:UIControlEventTouchUpInside]; [self.viewaddSubview:button]; } -(void)buttonAction:(UIButton*)sender { //点击按钮返回上一个页面同时通过block把这个值传到上一个页面 self.block(sender.titleLabel.text); [selfdismissViewControllerAnimated:nilcompletion:nil]; }
另外:block还有两个问题
1.怎么改变block里面的值
用上面的代码在ViewController.mviewDidLoad里面添加代码
1.局部变量 定义一个图片名字的Block */ //局部变量 void(^imageNameBlock)(NSString*imageName); //如果想修改Block里面的值需添加__block修饰 //__blockUIImage*image; imageNameBlock=^(NSString*imageName) { image=[UIImageimageNamed:imageName]; self.view.backgroundColor=[UIColorcolorWithPatternImage:image]; }; imageNameBlock(@"17.jpg");
就会出现Useofundeclaredidentifier'image'错误情况原因是我们试图改变block里面的值解决办法就是添加__block修饰(解注释
__blockUIImage*image;)就行了
2.block的循环引用
用上面的代码在ViewController.mviewDidLoad里面添加代码
//全局变量 //block循环引用解决我们用弱引用__block __weakViewController*VC=self; __blockUIImage*image=nil; imageNameBlock_1=^(NSString*imageName) { image=[UIImageimageNamed:imageName]; VC.view.backgroundColor=[UIColorcolorWithPatternImage:image]; }; UILabel*lable=[[UILabelalloc]initWithFrame:CGRectMake(100,200,200,100)]; lable.backgroundColor=[UIColorbrownColor]; [self.viewaddSubview:lable]; UITapGestureRecognizer*tap=[[UITapGestureRecognizeralloc]initWithTarget:selfaction:@selector(tap)]; [self.viewaddGestureRecognizer:tap];
再添加两个方法
-(void)loadData { imageNameBlock_1(@"17.jpg"); } -(void)viewWillAppear:(BOOL)animated { [selfloadData]; }
当出现循环引用是我们用__weak修饰下但具体机制还不太懂希望高人指点,感谢大家对毛票票的支持。