在两个ViewController之间传输数据

本文介绍iOS应用中ViewController间的双向数据传输方法,通过使用代理模式实现SecondViewController向ViewController的数据回传,并附带示例代码。

上一篇记录了如何在两个ViewController之间进行切换http://blog.youkuaiyun.com/k7arm/article/details/52726954。这里接着记录如在两个ViewController之间进行数据传输。
假设有两个ViewController,一个是ViewController,另一个是SecondViewController,现在要把ViewController中的数据传到SecondViewController中去,然后再把SecondViewController中的数据传输回ViewController中来,其实就是两个方向的传输。
下面先上代码:

//
//  ViewController.h
//  test-viewcontroller-presention
//
//  Created by ChrisBluez on 10/2/16.
//  Copyright © 2016 ChrisBluez. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController


@end

//
//  ViewController.m
//  test-viewcontroller-presention
//
//  Created by ChrisBluez on 10/2/16.
//  Copyright © 2016 ChrisBluez. All rights reserved.
//

#import "ViewController.h"
#import "SecondViewController.h"

@interface ViewController () <SecondViewControllerDelegate>
{
    UILabel *lab;
}
@end

@implementation ViewController



- (void)viewDidLoad {

    // 创建一个按钮
    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    btn1.frame = CGRectMake(38, 100, 300, 30);
    [btn1 setTitle:@"jump to the second page" forState:UIControlStateNormal];
    btn1.backgroundColor = [UIColor whiteColor];
    self.view.backgroundColor = [UIColor redColor];
    [btn1 addTarget:self action:@selector(jumpto) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn1];

    //创建一个label
    lab = [[UILabel alloc]initWithFrame:CGRectMake(18, 300, 300, 30)];
    lab.textColor = [UIColor yellowColor];
    lab.text = @"default text";
    [self.view addSubview:lab];

    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void) jumpto
{
    SecondViewController *sec = [[SecondViewController alloc] init];
    sec.delegate = self;
    sec.data = @"go to the second view";
    [self presentViewController:sec animated:YES completion:nil];
}


- (void) datafromcontroller:(NSString *)data
{
    lab.text = [NSString stringWithFormat:@"%@",data];
    NSLog(@"i am in the datafromcontroller");
}

@end
//
//  SecondViewController.h
//  test-viewcontroller-presention
//
//  Created by ChrisBluez on 10/2/16.
//  Copyright © 2016 ChrisBluez. All rights reserved.
//

#import <UIKit/UIKit.h>

@protocol SecondViewControllerDelegate <NSObject>

@required
- (void) datafromcontroller:(NSString *)data;

@end


@interface SecondViewController : UIViewController
{
    NSString *data;

}

@property (nonatomic,retain) NSString *data;
@property (nonatomic,weak) id<SecondViewControllerDelegate> delegate;

@end
//
//  SecondViewController.m
//  test-viewcontroller-presention
//
//  Created by ChrisBluez on 10/2/16.
//  Copyright © 2016 ChrisBluez. All rights reserved.
//

#import "SecondViewController.h"

@interface SecondViewController ()

@end

@implementation SecondViewController

@synthesize data;

- (void)viewDidLoad {
    // 创建一个按钮
    UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    btn1.frame = CGRectMake(38, 100, 300, 30);
    [btn1 setTitle:@"jump to the first page" forState:UIControlStateNormal];
    btn1.backgroundColor = [UIColor whiteColor];
    self.view.backgroundColor = [UIColor blueColor];
    [btn1 addTarget:self action:@selector(backto) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn1];

    //创建一个label
    UILabel *lab = [[UILabel alloc]initWithFrame:CGRectMake(38, 300, 300, 30)];
    lab.text = [NSString stringWithFormat:@"data :%@",data];
    lab.textColor = [UIColor whiteColor];
    [self.view addSubview:lab];

    //创建一个text,用来输入数据,然后传回给第1个viewcontroller


    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void) backto
{
    //if([_delegate respondsToSelector:@selector(datafromcontroller:)])
    {
        [_delegate datafromcontroller:@"i am come from the second view"];
        NSLog(@"enter delegate");
    }
   // else
    {
     //   NSLog(@"do not enter delegate");
    }



    [self dismissViewControllerAnimated:YES completion:nil];
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

从Viewcontroller.m文件中可以看到,在ViewController中向SecondViewController中传输数据时,先初始化一个SecondViewController的实例,然后直接给SecondViewcontroller的成员data赋值,然后使用presentviewController方法就行了。

看到这里我有一个疑问,就是为什么在Viewcontroller中定义了一个实例,给它的成员data赋完值之后,回到SecondViewController时候,再构造一个实例,就可以获得data的值了呢。难道每次使用SecondViewController出来的是同一个实例不成?因为只有这样才能保证在任何地方设置实例的变量后, 又可以在任何地方访问这个变量。为次搜了一apple的文档,终于找到了证据,参考链接为:https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/Singleton.html
且用了很形象的图来表示:
这里写图片描述
左边是典型的初始化实例,每次都会返回一个唯一的实例,而右边每次初始化实例时都返回同一个实例,这种方式叫做Singleton。这样就明白了,接下来继续。

刚才记录了如何从Viewcontroller发送数据给SecondViewController,下面来说如何从SecondViewController发送数据给Viewcontroller。最开始我想的是,这还不简单,如法炮制啊。在SecondViewController中直接给ViewController的实例成员赋值啊。但是这种方法不行,我遇到了这样的错误提示:
这里写图片描述

具体原因还不清楚,后来进到一个QQ群发了一个疑问,有一个好心的哥们回复我说不能这样用,具体原因也不太清楚,只好留着这个疑问等以后道行深了再去解决。

中间还需要去补习一下xcode的提示:__weak是什么意思?

既然不能再次使用Property就只好使用delegate了,其实在apple的官网上也说明了要使用delegate,参考链接:https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/DesignTips.html

这里写图片描述

既然这样,就只好先用delegate的方式了。

delegate其实我是把它理解成c中的回调函数了,也不知道对不对。在ios中是使用“方法”,“消息”这样的词来描述我们所说的函数或接口的,所以在ios中还有一个概念就是接收者,即当使用delegation时,谁来充当这个代理,也就是谁来实现这个回调函数的内容。回调函数的接口已经由SecondViewController.h中定义好了,所以剩下的就是谁来实现它。如果有多个实例来实现同一个接口的话,实现的内容不一样当然它的功能就不一样了,所以需要指定由谁来充当SecondViewController的代理。在我上面的那个示例中,只有一个接收者,即ViewController。当我们在ViewController中点击按钮时,就已经把ViewController作为SecondViewController的delegate了。

- (void) jumpto
{
    SecondViewController *sec = [[SecondViewController alloc] init];
    sec.delegate = self;
    sec.data = @"go to the second view";
    [self presentViewController:sec animated:YES completion:nil];
}

就是sec.delegate = self; 这一句实现了。当时我忘了写这一句,导致在第2个页面即SecondViewController中点击按钮时不能进入ViewController.m中的datafromcontroller()函数,让我好一顿找啊,一直没有找到问题,怀疑好半天人生。

最后的效果请见下图:
这里写图片描述

请忽略 default text2 ,这个当时是打算用来演示property从SecondViewController传递参数给ViewController的,但是失败了,就没有用上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值