iOS开发中视图控制器ViewControllers之间的数据传递

这里我们用一个demo来说明ios是如何在视图控制器之间传递重要的参数的。本文先从手写UI来讨论,在下一篇文章中讨论在storyboard中传递数据。

首先新建一个空工程,并添加一个根视图控制器类,如下图所示:

#

在函数didFinishLunchingWithOption中添加几行代码,完成后如下:

1
2
3
4
5
6
7
8
9
10
11
12
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
     
    RootViewController *myRootViewController = [[RootViewController alloc] init];
    myRootViewController.view.backgroundColor = [UIColor lightGrayColor];
    self.window.rootViewController = myRootViewController;
    return YES;
}

完成以后运行,iOS模拟器显示结果如下:

#

由图中可以看出,我们自定义的myRootViewController已经成功在启动时加载,显示出了一个浅灰色的界面。

随后如法炮制新建另一个viewController命名为FirstSubViewController,同时在RootViewController的viewDidLoad函数中添加如下代码:

1
2
3
4
5
6
7
8
9
10
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    UIButton *firstVC = [UIButton buttonWithType:UIButtonTypeSystem];
    firstVC.frame = CGRectMake(60, 244, 200, 80);
    [firstVC setTitle:@"显示下一个视图" forState:UIControlStateNormal];
    [firstVC addTarget:self action:@selector(displayNextViewController) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:firstVC];
}

之后还需定义一个函数,名为displayNextViewController,函数体暂时设为空。此时运行程序,界面中央将显示一个按钮“显示下一个视图”,但是单击该按钮没有任何反应。这是因为响应函数displayNextViewController还没有实现。现在在该函数中添加代码:

1
2
3
4
5
6
7
- (void)displayNextViewController
{
    FirstSubViewController *firstSubVC = [[FirstSubViewController alloc] init];
    [self presentViewController:firstSubVC animated:YES completion:^{
        NSLog(@"present first sub VC ok");
    }];
}

完成后运行程序发现,按钮已经有反应了,按下后回出现一个新的白色背景的新界面,这就是我们在这里定义的firstSubVC;

下一步实现界面的返回操作。在FirstSubViewController的viewDidLoad函数中建立一个回退按钮,并实现其响应函数。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
     
    UIButton *goBack = [UIButton buttonWithType:UIButtonTypeSystem];
    goBack.frame = CGRectMake(60, 244, 200, 80);
    [goBack setTitle:@"返回上级界面" forState:UIControlStateNormal];
    [goBack addTarget:self action:@selector(goBackToPreviousViewController) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:goBack];
}
 
- (void)goBackToPreviousViewController
{
    [self dismissViewControllerAnimated:YES completion:^{
        NSLog(@"Back to previous OK");
    }];
}

到此为止,我们已经通过presentViewController和dismissViewController实现了视图的切换,下面来考虑两个视图控制器之间的数据交流的问题。

在此之前,分别在RootViewController和FirstSubViewController中添加一个标签和文本框,作为数据的显示和输入部分。我们的目的是在FirstSubViewController中输入一个数字,然后再RootViewController显示出来。

在这两个类中分别用property来实现文本框和标签栏:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//RootViewController.m
@interface RootViewController ()
 
@property (strong,nonatomic) UILabel *lable;
 
@end
 
@implementation RootViewController
 
- (UILabel *)lable
{
    if (!_lable)
    {
        _lable= [[UILabel alloc] initWithFrame:CGRectMake(60, 150, 200, 30)];
        _lable.textAlignment = NSTextAlignmentCenter;
        _lable.text = @"Hello World!";
        _lable.backgroundColor = [UIColor whiteColor];
    }
    return _lable;
}
…..
@end
 
//FirstSubViewController
@interface FirstSubViewController ()
 
@property (strong,nonatomic) UITextField *inputText;
 
@end
 
@implementation FirstSubViewController
 
- (UITextField *)inputText
{
    if (!_inputText)
    {
        _inputText = [[UITextField alloc] initWithFrame:CGRectMake(60, 150, 200, 30)];
        _inputText.backgroundColor = [UIColor lightGrayColor];
    }
    return _inputText;
}
…..
@end

在这两个视图控制器的viewDidLoad中分别添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//RootViewController.m
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self.view addSubview:self.label];
     
    UIButton *firstVC = [UIButton buttonWithType:UIButtonTypeSystem];
    …..
}
…..
//FirstSubViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
     
    //添加输入框
    [self.view addSubview:self.inputText];
    UIButton *goBack = [UIButton buttonWithType:UIButtonTypeSystem];
    …..
}

在视图控制器之间进行数据传递可以通过多种方法,下面将逐个实验:

1、使用代理delegate的方法:

基本原理:FirstSubViewControllers试图改变RootViewController的数据,但是除了操作自己内部的数据的能力之外,不能改变其他类的数据。想要将这些数据传递出去,需要设置代理方法,获取FirstSubViewControllers中数据的类来遵循该方法,通过实现该代理协议中的方法来获取FirstSubViewControllers中的数据。

具体步骤:

首先在FirstSubViewController.h中定义协议:

1
2
3
4
5
6
@protocol FirstSubViewControllerDelegate <nsobject>
 
@optional
- (void)getStringFromFirstSubViewControllerDelegate:(NSString *)outputString;
 
@end</nsobject>

然后添加一个符合该协议的代理属性:

1
2
@property (nonatomic,weak) id<firstsubviewcontrollerdelegate> delegate;
</firstsubviewcontrollerdelegate>

在RootViewControlller.h中,声明该类符合FirstSubViewControllerDelegate协议:

1
@interface RootViewController : UIViewController<firstsubviewcontrollerdelegate></firstsubviewcontrollerdelegate>

在新建FirstSubViewController的实例后,将其delegate属性定义为self,同时实现协议中的方法,两个函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)getStringFromFirstSubViewControllerDelegate:(NSString *)outputString
{
    self.lable.text = outputString;
}
 
- (void)displayNextViewController
{
    FirstSubViewController *firstSubVC = [[FirstSubViewController alloc] init];
    firstSubVC.delegate = self;
    [self presentViewController:firstSubVC animated:YES completion:^{
        NSLog(@"present first sub VC ok");
    }];
}

最后在FirstSubViewController.m的goBackToPreviousViewController中添加一句向delegate属性发送获取数据的消息:

1
2
3
4
5
6
7
- (void)goBackToPreviousViewController
{
    [self.delegate getStringFromFirstSubViewControllerDelegate:self.inputText.text];
    [self dismissViewControllerAnimated:YES completion:^{
        NSLog(@"Back to previous OK");
    }];
}

这样,大功告成了,在FirstSubViewController中的输入框中输入的内容,在按返回按钮后回显示在第一个界面的标签上。

2、使用通知Notification的方法

关于通知的知识在未来将会详述,在这里只是简要介绍一种使用通知这一机制的方法。

在使用通知之前,必须在默认通知中心里添加一个所谓“观察者”和通知,这个通知是命名的,同时还指定了回调的方法。当该通知中心收到了某个对象发送了相应的通知时,将会调用指定的方法执行某项操作。通知的发送者同时还可以发送相应的消息作为通知的参数。

注册通知中心可以在RootViewController.m中的viewDidLoad函数的末尾添加如下函数:

1
2
//使用通知的方式实现
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeLabelText:) name:@"ChangeLabelTextNotification" object:Nil];

此外还要实现观察者的回调函数:

1
2
3
4
5
- (void)changeLabelText:(NSNotification *)notification
{
    id text = notification.object;
    _lable.text = text;
}

自此通知的接收端已经完成。

通知的发送端,只需在“返回上级界面”的相应函数中按照事先定义的名称发送通知和参数即可:

1
2
//使用通知方式实现
[[NSNotificationCenter defaultCenter] postNotificationName:@"ChangeLabelTextNotification" object:_inputText.text];

此时运行,将会发现和代理模式起到了相同的作用。

除了代理和通知之外,还有其他如KVO等方法,未来还会详细探讨。

iOS开发中视图控制器ViewControllers之间的数据传递的更多相关文章

  1. iOS开发中视图相关的小笔记:push、modal、popover、replace、custom

    在storyboard中,segue有几种不同的类型,在iphone和ipad的开发中,segue的类型是不同的. 在iphone中,segue有:push,modal,和custom三种不同的类型, ...

  2. ASP.NET MVC3中Controller与View之间的数据传递

    在ASP.NET MVC中,经常会在Controller与View之间传递数据,因此,熟练.灵活的掌握这两层之间的数据传递方法就非常重要.本文从两个方面进行探讨: 一.  Controller向Vie ...

  3. iOS开发之视图控制器(UIViewController)

    视图控制器应该在MVC设计模式中扮演控制层(C)的角色,UIViewController的职责对内管理与之关联的View,对外跟其他UIViewController通信和协调.一个视图控制器管理一个视 ...

  4. ASP.NET MVC3中Controller与View之间的数据传递总结

    一.  Controller向View传递数据 1.       使用ViewData传递数据 我们在Controller中定义如下: ViewData["Message_ViewData& ...

  5. Asp.net MVC中 Controller 与 View之间的数据传递

    在ASP.NET MVC中,经常会在Controller与View之间传递数据 1.Controller向View中传递数据 (1)使用ViewData["user"] (2)使用 ...

  6. MVC中Controller与View之间的数据传递

    一.Controller向View传递数据 Controller向View传递数据有3种形式: 通过ViewData传递 在Controller里面的Action方法中定义ViewData,并且赋值, ...

  7. iOS开发系列--视图切换

    概述 在iOS开发中视图的切换是很频繁的,独立的视图应用在实际开发过程中并不常见,除非你的应用足够简单.在iOS开发中常用的视图切换有三种,今天我们将一一介绍: UITabBarController ...

  8. 怎样实现IOS开发中的数据存储方式

    iOS 开发中,一般有如下几种数据存储方式.需要根据具体的业务场景,选择 合适的数据存储方式. (1)  用户默认设置 – 这种情况通常不需要用户干预,如游戏通关信息,Video 播放记录,或者 Ap ...

  9. IOS开发中UITableView(表视图)的滚动优化及自定义Cell

    IOS开发中UITableView(表视图)的滚动优化及自定义Cell IOS 开发中UITableView是非常常用的一个控件,我们平时在手机上看到的联系人列表,微信好友列表等都是通过UITable ...

随机推荐

  1. 转:Selenium中的几种等待方式,需特别注意implicitlyWait的用法

    最近在项目过程中使用selenium 判断元素是否存在的时候 遇到一个很坑爹的问题, 用以下方法执行的时候每次都会等待很长一段时间,原因是因为对selenium实现方法了解不足导致一直找不到解决方法. ...

  2. s5pv210 AD转换

    1:ADC:Analog-to-Digital Converter,模拟信号转数字信号,自然界一般为模拟信号,而SoC需要数字信号,所以之间通信需要ADC. 2:转换原理: 以逐次逼近式AD转换为例: ...

  3. jq中的evet.target

    1.this和event.target的区别: js中事件是会冒泡的,所以this是可以变化的,但event.target不会变化,它永远是直接接受事件的目标DOM元素: 2.this和event.t ...

  4. hrbustoj 1494(原题UVA 315 Network) 解题报告 tarjan求割点

    主要思路:使用tarjan选取一个根节点建立一个棵搜索树,判断一个点是割点的充分必要条件是,对于一个节点u如果他的孩子节点v的low值大于等于u的出生日期dfn值,进行下一步判断,如果u是我们选的根节 ...

  5. 转:Visual Studio进行Web性能测试- Part III

    原文作者:Ambily.raj 对于一个多用户的应用程序,性能是非常重要的.性能不仅是执行的速度,它包括负载和并发方面.Visual Studio是可以用于性能测试的工具之一.Visual Studi ...

  6. ASP php获取文件URL地址等方法

    $_SERVER["HTTP_REFERER"] rss中可用 echo next(explode("=", $_SERVER["QUERY_STRI ...

  7. c# 添加了按钮双击事件后,再删除掉代码会提示错误

    有两种方法:.清空属性窗口中的双击事件(doubleclick )右边的内容: .单击“发生错误”提示窗口的“否”后,再双击错误列表里的错误项,此时编辑窗口跳转为xx.Designer.cs,然后注释 ...

  8. 安卓图表引擎AChartEngine(五) - Dataset和Render参数介绍

    下面只讲解一个Renderer和一个DataSet,更多内容参看官方文档 DefaultRenderer: void addSeriesRenderer(int index, SimpleSeries ...

  9. java中HashMap详解(转)

    java中HashMap详解 博客分类: JavaSE Java算法JDK编程生活       HashMap 和 HashSet 是 Java Collection Framework 的两个重要成 ...

  10. DMLC深度机器学习框架MXNet的编译安装

    这篇文章将介绍MXNet的编译安装. MXNet的编译安装分为两步: 首先,从C++源码编译共享库(libmxnet.so for linux,libmxnet.dylib for osx,libmx ...