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

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等方法,未来还会详细探讨。

时间: 2024-10-15 19:38:01

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

iOS开发中标签控制器的使用——UITabBarController

正文 iOS开发中标签控制器的使用——UITabBarController 一.引言 与导航控制器相类似,标签控制器也是用于管理视图控制器的一个UI控件,在其内部封装了一个标签栏,与导航不同的是,导航的管理方式是纵向的,采用push与pop切换控制器,标签的管理是横向的,通过标签的切换来改变控制器,一般我们习惯将tabBar作为应用程序的根视图控制器,在其中添加导航,导航中在对ViewController进行管理. 二.创建一个标签控制器 通过如下的步骤,我们可以很简便的创建一个TabBarCo

[转]iOS开发之视图控制器(UIViewController)

视图控制器应该在MVC设计模式中扮演控制层(C)的角色,UIViewController的职责对内管理与之关联的View,对外跟其他UIViewController通信和协调.一个视图控制器管理一个视图(它可以有子视图),其view属性指向它所管理的视图.UIViewController类可以有子类,可以使用一个系统的UIViewController子类或者直接自己创建一个UIViewController的子类. 使用代码创建控制器和视图. 开始创建一个基于窗口的Empty Applicatio

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

</pre>在ASP.NET MVC<span style="font-family:宋体">中,经常会在</span>Controller<span style="font-family:宋体">与</span>View<span style="font-family:宋体">之间传递数据,因此,熟练.灵活的掌握这两层之间的数据传递方法就非常重要.本文从两个方面进行探讨:&

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

在ASP.NET MVC中,经常会在Controller与View之间传递数据,因此,熟练.灵活的掌握这两层之间的数据传递方法就非常重要.本文从两个方面进行探讨: Ø Controller向View传递数据 Ø View向Controller传递数据 一.Controller向View传递数据 1.       使用ViewData传递数据 我们在Controller中定义如下: ViewData[“Message”] = “Hello word!”; 然后在View中读取Controller中

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

在ASP.NET MVC中,经常会在Controller与View之间传递数据,因此,熟练.灵活的掌握这两层之间的数据传递方法就非常重要.本文从两个方面进行探讨: 一.  Controller向View传递数据 1.       使用ViewData传递数据 我们在Controller中定义如下: [csharp] view plain copy print? ViewData["Message_ViewData"] = " Hello ViewData!"; Vi

【iOS开发】视图控制器加载和卸载时的几个函数

1.-(void)loadView 你应该永远不要直接调用这个函数.当视图控制器的view属性被请求但是其值为nil时,该函数将会被调用.该函数加载或创建一个视图并把它分配给view属性. 如果视图控制器有一个与之相关联的nib文件,这个方法将会从nib文件中加载视图.当视图控制器的nibName属性的值不是nil时,就说明视图控制器有一个与之相关联的nib文件.如果你直接用initWithNibName:bundle:函数给视图控制器分配一个nib文件或者如果ios发现再应用程序中有一个以视图

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

视图控制器应该在MVC设计模式中扮演控制层(C)的角色,UIViewController的职责对内管理与之关联的View,对外跟其他UIViewController通信和协调.一个视图控制器管理一个视图(它可以有子视图),其view属性指向它所管理的视图.UIViewController类可以有子类,可以使用一个系统的UIViewController子类或者直接自己创建一个UIViewController的子类. 使用代码创建控制器和视图. 开始创建一个基于窗口的Empty Applicatio

IOS开发—禁止视图控制器自动调整status bar的风格

今天项目中的一个问题是当点击第三方库提供的按钮时,由于动画的效果使得status bar字体颜色会自动的变成黑色,但是status bar的背景为黑色,所以看起来就像是status bar消失了一样,但是按钮是第三方库中的内容,无法修改,这里我想到的是禁止status bar中的字体颜色自动改变.具体实现如下: 1.在项目的.plist文件中添加新的key:UIViewControllerBasedStatusBarAppearance 2.设置此key的value为NO 3.在didFinis

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

在ASP.NET MVC中,经常会在Controller与View之间传递数据 1.Controller向View中传递数据 (1)使用ViewData["user"] (2)使用ViewBag.user (3)使用TempData["user"] (4)使用Model(强类型) 区别: (1)ViewData与TempData方式是弱类型的方式传递数据,而使用Model传递数据是强类型的方式. (2)ViewData与TempData是完全不同的数据类型,View