IOS 控制器的数据传递 (顺传 and 逆传)
● 控制器之间的数据传递主要有2种情况:顺传和逆传
➢ 顺传
● 控制器的跳转方向: A ->C
● 数据的传递方向 : A -> C
● 数据的传递方式 : 在A的prepareForSegue:sender:方法中根据segue参数取得 destinationViewController,
也就是控制器C, 直接给控制器C传递数据 (要在C的viewDidLoad方法中取得数据,来赋值给界面上的UI控件)
顺传事例代码:
NJContatcsViewController.m(主控制器)
#import "NJContatcsViewController.h" #import "NJAddViewController.h" #import "NJContatc.h" #import "NJEditViewController.h" @interface NJContatcsViewController ()<UIActionSheetDelegate, NJAddViewControllerDelegate, NJEditViewControllerDelegate> /** * 点击注销按钮 */ - (IBAction)logout:(UIBarButtonItem *)sender; /** * 保存所有用户数据 */ @property (nonatomic, strong) NSMutableArray *contatcs; @end @implementation NJContatcsViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)logout:(UIBarButtonItem *)sender { UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"确定要注销?" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"确定" otherButtonTitles:nil]; [sheet showInView:self.view]; } #pragma mark - UIActionSheetDelegate - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if (0 != buttonIndex) return; // 移除栈顶控制器 [self.navigationController popViewControllerAnimated:YES]; } // 无论是手动类型的segue还是自动类型的segue, 在跳转之前都会执行该方法 // 控制器跳转之前(执行segue之前)执行 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // 0.判断目标控制器是添加还是编辑 // 1.取出目标控制器 UIViewController *vc = segue.destinationViewController; if ([vc isKindOfClass:[NJAddViewController class]]) { NJAddViewController *addVc = (NJAddViewController *)vc; // 2.设置代理 addVc.delegate = self; }else if ([vc isKindOfClass:[NJEditViewController class]]){ // 传递数据 NJEditViewController *editVc = (NJEditViewController *)vc; // 通过tableview获取被点击的行号 NSIndexPath *path = [self.tableView indexPathForSelectedRow]; // 取出被点击行的模型 NJContatc *c = self.contatcs[path.row]; NSLog(@"联系人列表 %p" , c); // 赋值模型 editVc.contatc = c; // 设置代理 editVc.delegate = self; } } #pragma mark - NJEditViewControllerDelegate - (void)editViewControllerDidClickSavBtn:(NJEditViewController *)editViewController contatc:(NJContatc *)cpmtatc { // 1.修改模型 // NSIndexPath *path = [self.tableView indexPathForSelectedRow]; // self.contatcs[path.row] = cpmtatc; // 2.刷新表格 [self.tableView reloadData]; } #pragma mark - NJAddViewControllerDelegate - (void)addViewControllerDidAddBtn:(NJAddViewController *)editViewController contatc:(NJContatc *)contatc { NSLog(@"添加了新联系人 %@ %@ %@", contatc.name, contatc.phoneNumber, contatc.email); // 1.保存数据到数组中 [self.contatcs addObject:contatc]; // 2.刷新表格 [self.tableView reloadData]; } - (NSMutableArray *)contatcs { if (_contatcs == nil) { _contatcs = [NSMutableArray array]; } return _contatcs; } #pragma mark - 数据源方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.contatcs.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *identifier = @"contatcs"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; // if (cell == nil) { // cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier]; // }re // 设置数据 NJContatc *c = self.contatcs[indexPath.row];//0 NSLog(@"cellForRowAtIndexPath %p", c); cell.textLabel.text = c.name; cell.detailTextLabel.text = c.phoneNumber; // 返回cell return cell; }
➢ 逆传 (使用代理方式)
● 控制器的跳转方向: A -> C
● 数据的传递方向 : C->A
● 数据的传递方式 : 让A成为C的代理, 在C中调用A的代理方法,通过代理方法的参数传递 数据给A
逆传事例代码:
NJEditViewController.h(创建代理)
#import <UIKit/UIKit.h> @class NJContatc, NJEditViewController; @protocol NJEditViewControllerDelegate <NSObject> - (void)editViewControllerDidClickSavBtn:(NJEditViewController *)editViewController contatc:(NJContatc *)cpmtatc; @end @interface NJEditViewController : UIViewController /** * 用于接收联系人列表传递过来的数据 */ @property (nonatomic, strong) NJContatc *contatc; @property (nonatomic, weak) id<NJEditViewControllerDelegate> delegate; @end
NJEditViewController.m(传递数据)
#import "NJEditViewController.h" #import "NJContatc.h" @interface NJEditViewController () @property (weak, nonatomic) IBOutlet UITextField *nameField; @property (weak, nonatomic) IBOutlet UITextField *phoneField; @property (weak, nonatomic) IBOutlet UIButton *saveBtn; /** * 编辑按钮点击事件 */ - (IBAction)editBtnOnClick:(UIBarButtonItem *)sender; /** * 保存按钮点击事件 * * @param sender <#sender description#> */ - (IBAction)saveBtnOnClick:(UIButton *)sender; @end @implementation NJEditViewController - (void)viewDidLoad { [super viewDidLoad]; // 设置姓名文本输入框 self.nameField.text = _contatc.name; // 设置电话文本输入框 self.phoneField.text = _contatc.phoneNumber; // 1.拿到通知中心 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; // 2.注册监听 // 注意点: 一定要写上通知的发布者 [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.nameField]; [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.phoneField]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)textChange { self.saveBtn.enabled = (self.nameField.text.length > 0 && self.phoneField.text.length > 0); } /* 因为控制器的view是懒加载的, 用到的时候再加载 而设置模型数据是在控制器跳转之前, 此时没有用到控制器的view, 所以控制器的view还没有创建, 它的子控件也没有创建 */ /* - (void)setContatc:(NJContatc *)contatc { _contatc = contatc; NSLog(@"%p - %p", self.nameField, self.phoneField); NSLog(@"%@ - %@", self.nameField, self.phoneField); // 设置姓名文本输入框 self.nameField.text = _contatc.name; // 设置电话文本输入框 self.phoneField.text = _contatc.phoneNumber; } */ - (IBAction)editBtnOnClick:(UIBarButtonItem *)sender { if (self.nameField.enabled) { // 当前是编辑状态 // 1.让文本输入框不可以交互 self.nameField.enabled = NO; self.phoneField.enabled = NO; // 2.隐藏保存按钮 self.saveBtn.hidden = YES; // 3.让键盘消失 // [self.phoneField resignFirstResponder]; [self.view endEditing:YES]; // 4.修改按钮标题 sender.title = @"编辑"; // 5.还原数据 // 设置姓名文本输入框 self.nameField.text = _contatc.name; // 设置电话文本输入框 self.phoneField.text = _contatc.phoneNumber; }else { // 当前是不可以编辑状态 // 1.让文本输入框可以交互 self.nameField.enabled = YES; self.phoneField.enabled = YES; // 2.显示保存按钮 self.saveBtn.hidden = NO; // 3.让电话文本输入框召唤出键盘 [self.phoneField becomeFirstResponder]; // 4.修改按钮标题 sender.title = @"取消"; } } - (IBAction)saveBtnOnClick:(UIButton *)sender { // 1.移除栈顶控制器 [self.navigationController popViewControllerAnimated:YES]; // 2.修改模型数据 NSLog(@"编辑界面 %p" , self.contatc); self.contatc.name = self.nameField.text; self.contatc.phoneNumber = self.phoneField.text; // 3.通知代理 if ([self.delegate respondsToSelector:@selector(editViewControllerDidClickSavBtn:contatc:)]) { [self.delegate editViewControllerDidClickSavBtn:self contatc:self.contatc]; } }
NJContatcsViewController.m(主控制器 实现代理方法)
#pragma mark - NJEditViewControllerDelegate - (void)editViewControllerDidClickSavBtn:(NJEditViewController *)editViewController contatc:(NJContatc *)cpmtatc { // 1.修改模型 // NSIndexPath *path = [self.tableView indexPathForSelectedRow]; // self.contatcs[path.row] = cpmtatc; // 2.刷新表格 [self.tableView reloadData]; } #pragma mark - NJAddViewControllerDelegate - (void)addViewControllerDidAddBtn:(NJAddViewController *)editViewController contatc:(NJContatc *)contatc { NSLog(@"添加了新联系人 %@ %@ %@", contatc.name, contatc.phoneNumber, contatc.email); // 1.保存数据到数组中 [self.contatcs addObject:contatc]; // 2.刷新表格 [self.tableView reloadData]; } - (NSMutableArray *)contatcs { if (_contatcs == nil) { _contatcs = [NSMutableArray array]; } return _contatcs; }