【iOS7的一些总结】2、视图控制器ViewControllers之间的数据传递(1)

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

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

#

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

- (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函数中添加如下代码:

- (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还没有实现。现在在该函数中添加代码:

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

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

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

- (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来实现文本框和标签栏:

//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中分别添加如下代码:

//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中定义协议:

@protocol FirstSubViewControllerDelegate <NSObject>

@optional
- (void)getStringFromFirstSubViewControllerDelegate:(NSString *)outputString;

@end

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

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

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

@interface RootViewController : UIViewController<FirstSubViewControllerDelegate>

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

- (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属性发送获取数据的消息:

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

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

2、使用通知Notification的方法

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

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

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

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

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

- (void)changeLabelText:(NSNotification *)notification
{
    id text = notification.object;
    _lable.text = text;
}

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

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

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

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

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

时间: 2025-01-02 14:19:33

【iOS7的一些总结】2、视图控制器ViewControllers之间的数据传递(1)的相关文章

【iOS7的一些总结】3、视图控制器ViewControllers之间的数据传递(2)

上文中记录了在手写代码实现UI的情况下,界面切换时不同视图控制器之间数据传递的机制.显示和消除界面使用的函数时presentViewController和dismissViewController函数,数据传递则可以采用代理.通知等机制.本文记录的是使用storyboard实现界面的情况下,采用segue相关的方法实现与上文中相同的功能. 首先要做的是新建一个单视图工程,建立完成后会生成一组(一个头文件和一个源文件称为一组)AppDelegate类,一组ViewController类,一个sto

iOS7应用开发5、视图控制器View Controller及其生命周期

1.UITextView: 该类与Label类类似,可显示多行,可以编辑内容,可以滚动查看内容: 包含属性NSTextStorage *textStorage,该类是NSMutableAttributedString的基类:修改该属性可以自动更新UITextView的内容: 包含属性UIFont *font,用于设置所有字符的字体: NSTextContainer *textContainer和NSLayoutManager *layoutManager属性,用于设置文本的其他一些属性: 2.视

【iOS7的一些总结】10、用列表显示内容(下)列表视图控制器UITableViewController

上篇简单总结了如何在一个视图控制器中建立一个列表视图UITableView来显示信息.其最核心概念,在于设置表视图的代理和数据源,并实现其协议规定的方法.而更简单的方法是,直接使用Cocoa Touch提供的一种专门用来显示列表视图的视图控制器--UITableViewController.这个类继承自UIViewController,并实现了一些特定的功能专门用来管理其中的列表视图. 同UIViewController相比,UITableViewController添加了多种新的propert

CoCoa编程中视图控制器与视图类介绍

UITabBarController类 选项卡类允许用户在多个视图控制器之间移动并在屏幕的底部可定制该栏.向不同的视图同时提供一次单击访问,向用户选择的屏幕和编辑底栏的屏幕同时提供More按钮. 选项卡类的方便之处就是 不需要象导航栏那样以栈的方式推入和弹出视图的操作,而是组建一系列的控制器(它们各自可以是UIViewController.UINavigationController.UITableViewController或其他任何类型的视图控制器),并通过设置栏的viewControlle

实例讲解iOS中的UIPageViewController翻页视图控制器_IOS

一.引言 UIPageViewController是iOS中少见的动画视图控制器之一,通过它既可以创建类似UIScrollView与UIPageControl结合的滚屏视图,也可以创建类似图书效果的炫酷翻页视图. UIPageViewController在iOS 5 SDK中首次引入,它使得开发者可以使用这个ViewController创建分页视图.在iOS 6中,这个类有了更新,支持滚动过渡效果.使用Page View,用户可以方便的通过手势在多个页面之间导航.UIPageViewContro

iOS翻页视图控制器UIPageViewController的应用

iOS翻页视图控制器UIPageViewController的应用 一.引言     UIPageViewController是iOS中少见的动画视图控制器之一,通过它既可以创建类似UIScrollView与UIPageControl结合的滚屏视图,也可以创建类似图书效果的炫酷翻页视图.UIPageViewController类似一个视图容器,其中每个具体的视图由各自的ViewController进行维护管理,UIPageViewController只进行协调与动画布置.下图可以很好的展现出UI

iOS 视图控制器转场详解(下)

推荐序 这是一篇长文,详细讲解了视图控制器转场的方方面面,配有详细的示意图和代码,为了使得文章在微信公众号中易于阅读,seedante 辛苦将大量长篇代码用截图的方式呈现,满满的诚意之作. 作者 seedante 是一个低调人士,只愿意透露他的 GitHub:https://github.com/seedante .感谢作者授权微信独家代理,本文的所有打赏归 seedante 所有. 插曲:UICollectionViewController 布局转场 前面一直没有提到这种转场方式,与三大主流转

手动操作导航控制器的子视图控制器的数组

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流之用,请勿进行商业用途.同时,转载时不要移除本申明.如产生任何纠纷,均与本博客所有人.发表该翻译稿之人无任何关系.谢谢合作! 你可能希望直接操作与特定导航控制器相关的子视图控制器的数组. 你可以使用UINavigationController的viewControllers属性修改其相关联的子视图

ios-检测视图控制器是否退出

问题描述 检测视图控制器是否退出 我有一段代码用来检测ViewController,具体是在另一个Navigation Stack中的VC弹出时执行: - (void) leftViewDidHide{ if ([((AppDelegate *)[UIApplication sharedApplication].delegate).frontViewController.navigationController.viewControllers objectAtIndex:1]) { SGServ