今个周末回家了,博客还没有更新!有时候会感觉倒不如不回家,之前安排的学习计划还要去完成,刚好这个周末有时间。但是最后,还是选择回家了,后面会想想
虽然热爱编程,热爱学习,更重要的要热爱生活。工作并不是生活的全部,回家见一下爸爸妈妈也是很好的,现在出来工作就更加发现没什么时间回家了。总得来说,若有恒,何必三更起五更眠;最无益,莫过一日暴十日寒。写词联,与各位共勉!
好,上回讲到xib for cell的缓存机制,今晚就来回顾一下多界面使用代理传值的方法。在不同的view中,传值的方法有多种:
1、比如在C/C++当中经常会使用全局变量并使用extern声明在所在的头文件中,然后哪个文件需要使用就包含这个头文件即可。
2、使用代理
3、使用持久化数据
4、使用block
当前就通过例子说明一下如何通过代理的方式实现不同界面的传值。大概的功能就是,在第一个界面的textfiled填入QQ号码,点击“login”登陆按钮,进入第二个界面。
然后在第二个界面点击完成按钮返回到第一个界面,并将第二个界面的“369”这个Libel的text传递给第一个界面的Libel显示。
1、首先按照下图搭建两个界面。使用UINavigation controller搭建两个视图,中间的view是“第一个”视图,最右边的是“第二个”视图。
2、为第二个view添加对应的子控件、方法以及协议。
声明:
#import <UIKit/UIKit.h>
@protocol LoginViewControlDelegate; // 每个地方需要用到协议的地方都需要先声明该协议
@interface secondViewController : UIViewController
@property (nonatomic,assign)bool open;
@property (weak, nonatomic) IBOutlet UILabel *secondLabel;//“369”的Libel
- (IBAction)secondClick; //完成按钮
extern int num;//外部声明全局变量,跟平时的C/c++一样
//定义一个协议代理
@property (nonatomic,weak) id<LoginViewControlDelegate> delegate;
@end
//定义一个协议
@protocol LoginViewControlDelegate <NSObject>
- (void) loginSuccess:(NSString *)userNameText;
@end
实现:(主要对第二个界面“完成”按钮添加对应的点击事件的方法)
- (IBAction)secondClick {
NSLog(@"****%@",self.secondLabel.text);
NSString *str = self.secondLabel.text;
[self.delegate loginSuccess:str];//向代理发送消息
[self.navigationController popToRootViewControllerAnimated:YES];//也可以使用系统自定按钮返回上一级界面
}
从第二view的代码可以知道,先是定义一个协议,并声明这个协议里面的方法。然后在按钮事件的方法中向代理方法消息。最后,使用
popToRootViewControllerAnimated
方法返回到上一级的菜单。当然,这个有系统默认的方法。
3、在第一个view中添加对应的控件、方法以及协议的实现
声明:
#import <UIKit/UIKit.h>
#import "secondViewController.h"
@protocol LoginViewControlDelegate; //添加协议
@interface QTViewController : UIViewController <LoginViewControlDelegate>//view遵守代理的协议
@property (weak, nonatomic) IBOutlet UITextField *textFiled;//QQ textfiled
@property (weak, nonatomic) IBOutlet UILabel *mainLabel; // 需要显示传递过来内容的Libel
- (IBAction)login;//登陆按钮的方法
@end
实现:
- (IBAction)login {
if(self.textFiled.text.length ==0){
NSLog(@"write your account\r\n");
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"警告:请输入QQ" delegate:nil cancelButtonTitle:@"Ok" destructiveButtonTitle:@"好的" otherButtonTitles:@"test", @"test2", nil];
// 显示到什么地方
[sheet showInView:self.view];
}else{
[self performSegueWithIdentifier:@"login" sender:nil];
}
}
/*
在界面切换之前就调用下面的函数
*/
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
//在这里可以得到segue两端的控制器,得到两个控制器之后,就可以通过不同的消息传递方式实现数据交换
//可以通过协议的方式传递等等
NSLog(@"%@",segue.sourceViewController);
NSLog(@"%@",segue.destinationViewController);
NSLog(@"num=%d",num); //访问全局变量,实现数据的交换
secondViewController *second = (secondViewController *)segue.destinationViewController;
second.delegate = self;//通过segue获取下一个页面的控制前,并设置下一个控制器的代理是当前页面控制器
//必须通过协议的方式来实现不同的view中的数据传值
// secondViewController *send = (secondViewController *)segue.destinationViewController;
}
- (void) loginSuccess:(NSString *)userNameText //实现代理协议的方法
{
self.mainLabel.text = userNameText; //接收其他控制器发送过来的数据
NSLog(@"protocol is right,i get the msg");
}
@end
从上面的代理我们可以得知,要成为第二界面的代理,必须先要遵守代理协议。并在代理协议中设置当前的view成为第二个界面的代理,最后获取第二个代理发送过来的消息,并处理消息。
另外,在第一个界面的“login”登陆界面,如果textfiled是空,将会使用“UIActionsheet”来作“警告提示”。
还有一个技巧是,
<strong>- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender</strong>
我们已经知道一个segue两端对应了两个不同的视图。该方法每次在界面切换之前都会执行的。因此,直接在该方法中首先获取了两端对应的view,然后设置代理即可。
要注意的是,当前相当于只有一个segue,所以每次传入的segue都是确定于当前界面的segue。如果多个界面的话,由于segue是可以设置ID号,可以根据ID号就可以判断
当前是哪一条segue了。
总结:
从实现的效果来看,代理的方式只能够用于单向传值。
步骤都是:声明协议---设置代理--实现代理的协议方法--向代理发送消息--代理接受并处理消息。
<代码后面再补上>