zoukankan      html  css  js  c++  java
  • iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例)

    iOS页面间传值的方式(NSUserDefault/Delegate/NSNotification/Block/单例)

    实现了以下iOS页面间传值:1.委托delegate方式;2.通知notification方式;3.block方式;4.UserDefault或者文件方式;5.单例模式方式;6.通过设置属性,实现页面间传值

    在iOS开发中,我们经常会遇到页面间跳转传值的问题,现归纳总结一下:

    情况1:A页面跳转到B页面

    方法:

    在B页面的控制器中,编写对应的属性,在A页面跳转到B页面的地方,给B的属性赋值即可

    1.//SecondViewController.h
    1.@property(nonatomic) NSInteger flag;//当前系统标示(0:其他传值方式;1:block传值方式)

    在A页面的试图控制器中

    1.//RootViewController.m
    1.- (IBAction)showSecondView:(id)sender {
    2.SecondViewController *second = [[SecondViewController alloc] initWithNibName:@'SecondViewController'bundle:nil];
    3.second.delegate = self;
    4.second.flag = 0;
    5.[self presentViewController:second animated:YES completion:nil];
    6.}

    情况2:A页面跳转到B页面,B页面再跳转回A页面

    主流方案:

    (1)通过委托delegate的方式实现

         设置协议及方法          
    1.//SecondViewController.h
    1.@protocol secondViewDelegate
    2.-(void)showName:(NSString *)nameString;
    3.@end

    设置代理(为防止循环引用,此处采用了weak)

    1.//SecondViewController.h
    1.@interface SecondViewController : UIViewController
    2.@property (nonatomic, weak)id<secondViewDelegate> delegate;
    3.@property (nonatomic, copy) ablock block;
    4.@end
           调用
    01.//SecondViewController.m
    02.- (IBAction)delegateMethod:(id)sender {
    03.if ([self notEmpty]) {
    04.[self.delegate showName:self.nameTextField.text];
    05.[self dismissViewControllerAnimated:YES completion:nil];
    06.}else{
    07.[self showAlert];
    08.}
    09.}

        显示  
    1.//RootViewController.m
    2.-(void)showName:(NSString *)nameString{
    3.self.nameLabel.text = nameString;
    4.}
        最重要也是最容易忽略的,就是一定要设置delegate的指向。    

    (2)通过通知notification的方式实现

         在B页面的控制器中,发送通知:
    01.//SecondViewController.m
    02.- (IBAction)notificationMethod:(id)sender {
    03.if ([self notEmpty]) {
    04.[[NSNotificationCenter defaultCenter] postNotificationName:@'ChangeNameNotification' object:self userInfo:@{@'name':self.nameTextField.text}];
    05.[self dismissViewControllerAnimated:YES completion:nil];
    06.}else{
    07.[self showAlert];
    08.}
    09.}

    在A页面的控制器中,注册通知:

    1.//RootViewController.m
    2.- (void)viewDidLoad
    3.{
    4.[super viewDidLoad];
    5.// Do any additional setup after loading the view from its nib.
    6.[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ChangeNameNotification:) name:@'ChangeNameNotification' object:nil];
    7.}

    当我们不使用时,要记得删掉通知:

    1.//RootViewController.m
    2.-(void)dealloc{
    3.[[NSNotificationCenter defaultCenter] removeObserver:self];
    4.}

     调用,显示

    1.//RootViewController.m
    2. 
    3.-(void)ChangeNameNotification:(NSNotification*)notification{
    4.NSDictionary *nameDictionary = [notification userInfo];
    5.self.nameLabel.text = [nameDictionary objectForKey:@'name'];
    6.}

    (3)block方式实现

    block介绍:http://blog.csdn.net/totogo2010/article/details/7839061

    链接一篇描述block回调挺有意思的文章: http://blog.csdn.net/mobanchengshuang/article/details/11751671

    分析:

    在B试图控制器中,定义一个block,参数为字符串

    1.//SecondViewController.h
    2.typedef void (^ablock)(NSString *str);
    1.//SecondViewController.h
    2. 
    3.@property (nonatomic, copy) ablock block;

    在B试图控制器中,当输入名字,点击对应的确定按钮后

    01.- (IBAction)blockMethod:(id)sender {
    02.if ([self notEmpty]) {
    03.if (self.block) {
    04.self.block(self.nameTextField.text);
    05.[self dismissViewControllerAnimated:YES completion:nil];
    06.}
    07.}else{
    08.[self showAlert];
    09.}
    10.}

    在A试图显示,回调block

    1.- (IBAction)showSecondWithBlock:(id)sender {
    2.SecondViewController *second = [[SecondViewController alloc] initWithNibName:@'SecondViewController'bundle:nil];
    3.[self presentViewController:second animated:YES completion:nil];
    4.second.block = ^(NSString *str){
    5.self.nameLabel.text = str;
    6.};
    7.}

    在查阅资料的过程中,我还看到了以下几种方案:

    (1)使用SharedApplication,定义一个变量来传递(感觉和单例的方式一样)

    (2)使用文件,或者NSUserdefault来传递

    01.//通过文件或者UserDefault方式存值(感觉不太适合此类传值,如果要用文件或者UserDefault方式存值的话,可以考虑此方式)
    02.- (IBAction)userDefaultMethod:(id)sender {
    03.if ([self notEmpty]) {
    04.[[NSUserDefaults standardUserDefaults] setObject:self.nameTextField.text forKey:@'myNameText'];
    05.[self dismissViewControllerAnimated:YES completion:nil];
    06.}else{
    07.[self showAlert];
    08.}
    09.}

    在A试图控制器显示

    01.-(void)viewDidAppear:(BOOL)animated{
    02.[super viewDidAppear:animated];
    03.//如果想测试通过UserDefault方式传值或者通过单例方式传值,取消以下注释即可
    04./*
    05.if ([[[NSUserDefaults standardUserDefaults] objectForKey:@'myNameText'] length] != 0) {
    06.self.nameLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:@'myNameText'];
    07.[[NSUserDefaults standardUserDefaults] setObject:@'' forKey:@'myNameText'];
    08.}
    09.DataSource *dataSource = [DataSource sharedDataSource];
    10.if ([dataSource.myName length] != 0) {
    11.self.nameLabel.text = dataSource.myName;
    12.dataSource.myName = @'';
    13.}
    14.*/
    15.}

    (3)通过一个单例的class来传递

    B试图控制器

    01.//通过单例方式传值(感觉不太适合此类传值,如果要用单例方式传值的话,可以考虑此方式)
    02.- (IBAction)singletonMethod:(id)sender {
    03.if ([self notEmpty]) {
    04.DataSource *dataSource = [DataSource sharedDataSource];
    05.dataSource.myName = self.nameTextField.text;
    06.[self dismissViewControllerAnimated:YES completion:nil];
    07.}else{
    08.[self showAlert];
    09.}
    10.}

    A试图控制器显示

    01.-(void)viewDidAppear:(BOOL)animated{
    02.[super viewDidAppear:animated];
    03.//如果想测试通过UserDefault方式传值或者通过单例方式传值,取消以下注释即可
    04./*
    05.if ([[[NSUserDefaults standardUserDefaults] objectForKey:@'myNameText'] length] != 0) {
    06.self.nameLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:@'myNameText'];
    07.[[NSUserDefaults standardUserDefaults] setObject:@'' forKey:@'myNameText'];
    08.}
    09.DataSource *dataSource = [DataSource sharedDataSource];
    10.if ([dataSource.myName length] != 0) {
    11.self.nameLabel.text = dataSource.myName;
    12.dataSource.myName = @'';
    13.}
    14.*/
    15.}
    16.@end

    这里面用到了单例模式,编写了DataSource这个类,存放数据

    01.//
    02.//  DataSource.h
    03.//  TestCallBack
    04.//
    05.//  Created by csdc-iMac on 14-7-17.
    06.//  Copyright (c) 2014年 JuneWang. All rights reserved.
    07.//
    08. 
    09.#import <Foundation/Foundation.h>
    10. 
    11.@interface DataSource : NSObject
    12.@property (nonatomic, strong) NSString *myName;
    13.+(DataSource*)sharedDataSource;
    14.@end 
    01.//
    02.//  DataSource.m
    03.//  TestCallBack
    04.//
    05.//  Created by csdc-iMac on 14-7-17.
    06.//  Copyright (c) 2014年 JuneWang. All rights reserved.
    07.//
    08. 
    09.#import 'DataSource.h'
    10. 
    11.@implementation DataSource
    12.+(DataSource *)sharedDataSource{
    13.static DataSource *dataSource = nil;
    14.static dispatch_once_t once;
    15.dispatch_once(&once, ^{
    16.dataSource = [DataSource new];
    17.});
    18.return dataSource;
    19.}
    20.@end

    程序运行截图

    A视图:

    B视图

    当输入姓名,并点击对应的确认按钮后,会回到A视图,并显示在B视图中输入的姓名

    祝:玩得开心,有什么别的办法或者不正确的地方,欢迎指正。

    如果写得不详细,可以通过源码分析。

     参考:http://blog.csdn.net/cocoarannie/article/details/11857141

    http://www.cnblogs.com/heri/archive/2013/03/18/2965815.html

    源码地址:https://github.com/wangtao169447/PassValue

    出处:http://www.cnblogs.com/JuneWang/p/3850859.html 

  • 相关阅读:
    二分图 洛谷P2055 [ZJOI2009]假期的宿舍
    并查集 洛谷P1640 [SCOI2010]连续攻击游戏
    贪心 洛谷P2870 Best Cow Line, Gold
    贪心 NOIP2013 积木大赛
    快速幂 NOIP2013 转圈游戏
    倍增LCA NOIP2013 货车运输
    树形DP 洛谷P2014 选课
    KMP UVA1328 Period
    动态规划入门 BZOJ 1270 雷涛的小猫
    KMP POJ 2752Seek the Name, Seek the Fame
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/5078429.html
Copyright © 2011-2022 走看看