iOS不同界面之间传值的几种方法

来源:互联网 发布:pe备份数据 编辑:程序博客网 时间:2024/04/27 15:49

1.通过storyboard添加的segue

我们都知道 segue完成界面的跳转是通过一个performSegueWithIdentifier函数  这个函数由当前的视图控制器调用

我们分析下performSegueWithIdentifier方法完整的执行过程

  • 根据identifier去storyboard中找到对应的线,新建UIStoryboardSegue对象
  • 设置Segue对象的sourceViewController(来源控制器)
  • 新建并且设置Segue对象的destinationViewController(目标控制器)
2.设置完之后就开始跳转 调用sourceViewController的下面方法,做一些跳转前的准备工作并且传入创建好的segue对象

- (void)prepareForSegue:(UIStoryboardSegue *)segue    sender:(id)sender;

//这个sender是当初perform seguewithidentifier:sender中传入的sender

3.调用segue对象的- (void)perform;方法执行界面跳转操作

3.1取得sourceViewController所在的NavigationController

3.2调用NavigationController的push方法将destinationViewController压入栈中 完成跳转


所以 在源控制器中 只要实现以下代码 就能修改标题:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

    //1.拿到目标控制器

    UIViewController *vc = segue.destinationViewController;

    //2. 设置目标控制器的标题

    vc.navigationItem.title =self.loginText.text;

    

    vc.title = [NSStringstringWithFormat:@"%@的联系人列表",self.loginText.text];

}



另外注意的是,注册一个通知,在这个通知销毁的时候一定要取消监听,

- (void)viewDidLoad {

    [superviewDidLoad];

    //1.增加两个通知

    [[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(textChanged)name:UITextFieldTextDidChangeNotificationobject:self.nameText];

    [[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(textChanged)name:UITextFieldTextDidChangeNotificationobject:self.phoneNumber];

}

/*取消监听*/

- (void)dealloc{

    [[NSNotificationCenterdefaultCenter]removeObserver:self];

}


2.从后一个界面传值到前一个界面 这里比上面稍微复杂些,方法也比较多

假设我们现在要从LWAddViewController传值到LWContactViewController这个界面

2.1 

首先,我们在LWContactViewController声明一个设置值的方法,代码如下:

- (void)setName:(NSString *)name andNumber:(NSString *)num;

在.m文件中是对该方法的实现

我们先简单的打印一下,看看值能不能正确的传递过来

- (void)setName:(NSString *)name andNumber:(NSString *)num{

    NSLog(@"name = %@ num = %@",name,num);

}


LWAddViewController中  先来声明一个LWContactViewController对象的属性

/*声明一个contactVC属性*/

@property (nonatomic,strong)LWContactViewController *Contact;

导入前一个页面的头文件

在点击跳转的按钮方法中 实现以下代码:

/*点击添加按钮*/

- (IBAction)addBtnClickd {

    LWContactViewController *conc = [[LWContactViewControlleralloc]init];

    self.Contact = conc;

    [self.ContactsetName:self.nameText.textandNumber:self.phoneNumber.text];

     [self.navigationControllerpopViewControllerAnimated:YES];

}


点击运行 OK现在就能正确的把数据传递过来了 效果如图


2.2 我们知道,无论是自动类型还是手动类型的segue都会在跳转前执行这个方法

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

    /*取出目标控制器*/

    LWAddViewController *addVC = (LWAddViewController *)segue.destinationViewController;

    /*设置目标控制器的来源控制器属性*/

    addVC.contact = self;

}


我们在跳转之前  取出目标控制器  设置他的contact属性为self  这样当点击按钮添加联系人的时候 我们直接可以通过下面代码来实现:


- (IBAction)addBtnClickd {

    [self.contactsetName:self.nameText.textandNum:self.phoneNumber.text];

}


实现的效果是一样的
2.3通过代理的方式来实现
在LWAddViewController中 首先声明一个协议 通过以下代码实现:

/*实现一个协议*/

@protocol LWAddViewControllerDelegate <NSObject>

- (void)addViewControllerAddBtnClicked:(LWAddViewController *)addViewController;

@end


再设置一下代理

/*实现一个代理*/

@property (nonatomic,weak)id<LWAddViewControllerDelegate> delegate;


在按钮点击的跳转方法中(就是从当前页面跳到前一个页面 传值也指的是从当前页面传到前一个页面) 实现以下代码

/*点击添加按钮*/

- (IBAction)addBtnClickd {

    /*如果能响应这个事件*/

    if ([self.delegaterespondsToSelector:@selector(addViewControllerAddBtnClicked:)]) {

        [self.delegateaddViewControllerAddBtnClicked:self];

    }

}


在这 加入代理

在LWContactViewController中 首先设置self为segue目标控制器的代理  代码如下:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

    LWAddViewController *addVC  = (LWAddViewController *)segue.destinationViewController;

    addVC.delegate  = self;

}

再实现代理方法:

/*实现代理方法*/

- (void)addViewControllerAddBtnClicked:(LWAddViewController *)addViewController{

    NSLog(@"成功添加了新联系人!");

}

点击运行 就能成功打印出来了 但是这样写仍然有需要完善的地方  因为两个viewcontroller都需要互相import对方 耦合度太高了  显然这不是我们希望看到的  解决方法是,将需要传递的数据对象抽象成一个模型 实现代码:

#import <Foundation/Foundation.h>

LWContact中定义了两个属性 name和num

@interface LWContact : NSObject

@property (nonatomic,copy)NSString *name;

@property (nonatomic,copy)NSString *num;

@end


在协议的声明中 改成:

@protocol LWAddViewControllerDelegate <NSObject>

/*协议*/

- (void)addViewControllerAddBtnClicked:(LWContact *)contact;


@end


在执行跳转传数据的按钮的响应方法中 实现以下代码:

- (IBAction)addBtnClickd {

    /*是否能响应*/

    if ([self.delegaterespondsToSelector:@selector(addViewControllerAddBtnClicked:)]) {

        LWContact *contact = [[LWContactalloc]init];

        contact.name = self.nameText.text;

        contact.num = self.phoneNumber.text;

        [self.delegateaddViewControllerAddBtnClicked:contact];

        [self.navigationControllerpopViewControllerAnimated:YES];

    }

}

注意到了没 假使以后产品经理对产品需求发生了变化,需要我们往属性中添加新属性 我们不必再修改很多地方 一个一个添加新增的属性参数  只需要在模型中进行修改即可
同样的 在LWContactViewController中 我们需要修改的是代理的实现方法  实现代码:

/*实现代理方法*/

- (void)addViewControllerAddBtnClicked:(LWContact *)contact{

    NSLog(@"name = %@ num = %@",contact.name,contact.num);

}

运行一下 同样实现了传递数据的功能  

0 0
原创粉丝点击