iOS页面传值方式

应用于:

  1. 两个互动的界面:1)页面一跳转到页面二,页面一的textField的值传给页面二的label。2)A页面跳转到B页面,B页面再跳转回A页面(注册页面跟登录页面)
  2. 两个不互动的两个界面:数据持久层跟表示层的数据交互。

几种传值方式:

  1. 属性传值 
  2. 委托delegate方式
  3. 通知notification方式
  4. block方式
  5. 单例模式方式
  6. UserDefault或者文件方式

1.属性传值(顺传):

  1. 需要定义一个公开的属性
  2. 需要一个你需要传值的对象
  3. 进行属性赋值

实现:A、B两个界面,通过按钮将A界面textField的值传给页面B的label。

A:ViewController   B:DetailViewController

#import "ViewController.h"

  @interface ViewController ()

  @property (nonatomic, strong) UITextField *textField;

 @end

  @implementation ViewController

-(void)buttonAction:(UIButton *)button

{

DetailViewController *detailViewController = 

[[DetailViewController alloc]init];//用下一个视图的属性接受想要传过去的值,属性传值

detailViewController.firstValue = self.txtFiled.text;

[self.navigationController pushViewController:second animated:YES];

}

DetailViewController界面

#import "DetailViewController.h"

  @interface DetailViewController ()

  @property (nonatomic, weak) NSString firstValue;//接收textField传过来的值。

 @end

2.代理传值(顺传倒传都可以)

delegate只能是一对一之间的。他只能是navigation的栈里面的相邻控制器传值, 不能跨控制器传值。比如:a到b,b到c.,而不能从c传到a.

  1. 拟定⼀份协议(命名一般是XXXDelegate),协议里面的⽅法的参数取决于你要传递的内容
  2. 设置代理人属性(再次强调,使用assign防⽌循环引用)
  3. 在需要调⽤的地⽅调⽤,这⼀步比较抽象,⽐如上面所讲例⼦子,我们是需要在button点击的时候
  4. 传值并且取消界面,所以我们的delegate就在这个⽅面的进⾏调用
  5. 让相应的对象成为代理人,⼀般都是在创建的时候指定一个代理⼈
  6. 遵守协议,并且实现相应的方法,然后在方法中进行逻辑处理

实现:A页面push到B页面,如果 B页面的信息想回传(回调)到A页面,用代理传值,其中B定义协议和声明代理,A确认并实现代理,A作为B的代理

A页面:RootViewControllers  B页面:DetailViewControllers

ViewControllers.h文件

#import <UIKit/Uikit.h>

@class DetailViewController;

@protocol PassingValueDelegate<NSObject>//拟定协议

@optional

-(void)passValues:(NSString *)values;//定义协议方法(values你想要传递的内容)

@end

@interface ViewControllers: UIViewController

@property (nonatomic, weak)id< PassingValueDelegate > delegate; (valueDelegate)//设置代理属性,通过其传值(为防止循环引用,此处采用了weak或者assign)

点击按钮事件函数(调用代理)

-(void)trendBtnClick{ 

    //create the view 

  DetailViewController * detailViewController = [[DetailViewController alloc] initWithNibName:@" DetailViewController " bundle:nil]; //传值并且取消界面

    self.delegate (自己命名的valueDelegate )= detailViewController; //设置代理 ,让相应的对象成为代理人

    [self.trendDelegate passValues:@""]; 

//页面跳转  

}

DetailViewController.h 文件

引用ViewController的头文件,并添加代理协议如下

#import "ViewController.h" 

@interface TrendViewController : UIViewController<PassTrendValueDelegate>{ 

} 

@end

实现代理函数:

#pragma mark 实现传值协议方法 

-(void)passValues:(NSString *)values{ 

NSLog(@"values=%@",values);  

}

最重要也是最容易忽略的,就是一定要设置delegate的指向

3.通知传值(顺传倒传都可以)第三个页面的值传给第一个页面

谁要监听值的变化,谁就注册通知 ,特别要注意,通知的接受者必须存在这一先决条件不用通知的时候,记得移除。

  1. 在第三个界面中, 建⽴一个通知中心, 通过通知中心, 发送通知(发送通知的过程就是传值的过程,将要传输的值作为object的值传给第一个界面
  2. 在第⼀个界面建⽴一个通知中心, 通过通知中⼼,注册一个监听事件
  3. 在第一个界⾯中,设置接收到通知的事件。
  4. 在第⼀个界⾯面中的dealloc中, 将通知中心remove掉

任何对象对可以发送通知到中心,同时任何对象可以监听中心的通知。
发送通知的代码如下:

[[NSNotificationCenter defaultCenter] postNotificationName:@”myNotificationName” object:broadcasterObject];

注册接收通知的代码如下:

[[NSNotificationCenter defaultCenter] addObserver:listenerObject selector:@selector(receivingMethodOnListener:) name:@”myNotificationName” object:nil]; 

实现:将B界面的值传给A界面,所以B界面发送通知到通知中心,A界面注册成为监听者,监听B值的变化,接受从通知中心回传的B的值。如果c页面也想接受B的值,也同样注册成为监听者就行。(所以可以实现多对多)

A界面:RootViewController B界面:SecondViewController

B界面建立通知中心,将要传的值nameTextField.text通过通知中心发送

//SecondViewController.m

-(IBAction)notificationMethod:(id)sender {

[[NSNotificationCenter defaultCenter] postNotificationName:@'ChangeNameNotification'  object:self  userInfo:@{@'name':self.nameTextField.text}];

[self dismissViewControllerAnimated:YES completion:nil];

}

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

//RootViewController.m

- (void)viewDidLoad.{

[super viewDidLoad];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ChangeNameNotification:) name:@'ChangeNameNotification' object:nil];

}

调用,显示

//RootViewController.m

-(void)ChangeNameNotification:(NSNotification*)notification{

NSDictionary *nameDictionary = [notification userInfo];

self.nameLabel.text = [nameDictionary objectForKey:@'name'];

.}

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

//RootViewController.m

-(void)dealloc{

[[NSNotificationCenter defaultCenter] removeObserver:self];

}

4. block传值(顺传倒传都可以)block同样用于回调

  1. 为block取别名。并且在参数列表中将需要传递的参数写形参
  2. 设置block属性(注意使用copy)
  3. 设置一个方法持有当前block
  4. 在合适的地方进行调用类似代理
  5. 在创建该对象的地方进行block方面的调用

//block语法

//返回值类型 (^block参数名) (参数类型 参数名) = ^返回值类型 (参数类型 参数名)

实现:将B界面的textField.text传给A界面的Label

A页面:RootViewControllers  B页面:DetailViewControllers

DetailViewController文件

#import <UIKit/Uikit.h>

typedef void (^DetailBlock)(NSString *);//block取别名。并且在参数列表中将需要传递的参数写形参

@interface DetailViewController : UIViewController

@property (nonatomic, copy) PassingValueBlock passingvalue;//设置block属性(注意使用copy)

@property (weak, nonatomic) UITextField *inputTF;

@end

- (IBAction)BtnAction:(id)sender {    

    //判断block是否为空

    if (self.NextViewControllerBlock) {

        self.NextViewControllerBlock(self.inputTF.text);       

    }

    [self.navigationController popViewControllerAnimated:YES];

}//点击按钮到A界面

RootViewController.m

@property (strong, nonatomic) UILabel *textLabel;

-(void)handleButton: (NSString*)sender{
DetailViewController *detailViewController = [[DetailViewController alloc]init]; detailViewController.passingValue=^( NSString* str){
self. textLabel.text= str;} [self.navigationController pushViewController:detailViewController animated:YES]; }

5. 单例传值(顺传倒传都可以)

单例的好处就在于只是创建了一次,其余任何时候访问到的对象都是同一个,所以很多时候用到用户的一些信息都是保存在单例中的,这样就不需要多次传值了,只需要再次创建单例就可以了

AppStatus.h  创建一个单例类 AppStatus

#import <Foundation/Foundation.h>

@interface AppStatus : NSObject

{

    NSString *_contextStr;

}

@property(nonatomic,retain)NSString *contextStr;

+(AppStatus *)shareInstance;

@end

AppStatus.m

#import "AppStatus.h"

@implementation AppStatus

@synthesize contextStr = _contextStr;

static AppStatus *_instance = nil;

+(AppStatus *)shareInstance

{

    if (_instance == nil)

    {

        _instance = [[super alloc]init];

    }

    return _instance;

}

-(id)init

{

    if (self = [super init])

    {       

    }

    return self;

}

@end

RootViewController.h

#import "RootViewController.h"

#import "DetailViewController.h"

#import "AppStatus.h"

@interface RootViewController ()

@end

@implementation RootViewController

-(void)pushAction:(id)sender

{

    tf = (UITextField *)[self.view viewWithTag:];

 //单例传值  将要传递的信息存入单例中(共享中)

  //  [[AppStatus shareInstance]setContextStr:tf.text]; 跟下面这种写法是等价的

    [AppStatus shareInstance].contextStr = tf.text;

    //导航push到下一个页面

    DetailViewController *detailViewController = [[DetailViewController alloc]init];

    //导航push到下一个页面

    [self.navigationController pushViewController:detailViewController animated:YES];

} 

@end

DetailViewController.h

#import <UIKit/UIKit.h>

@protocol ChangeDelegate;//通知编译器有此代理

@interface DetailViewController : UIViewController

{

    UITextField *textField;

}

@end

#import "DetailViewController.h"

#import "AppStatus.h"

@interface DetailViewController ()

@end

@implementation DetailViewController

@synthesize naviTitle = _naviTitle;

-(void)loadView

{

    self.view = [[[UIView alloc]initWithFrame:CGRectMake(, , , )]autorelease];

    //单例

    self.title = [AppStatus shareInstance].contextStr;

    textField = [[UITextField alloc]initWithFrame:CGRectMake(, , , )];

    textField.borderStyle = UITextBorderStyleLine;

    [self.view addSubview:textField];

    UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDonetarget:self action:@selector(doneAction:)];

    self.navigationItem.rightBarButtonItem = doneItem;

    [doneItem release];

}

//这个方法是执行多遍的  相当于刷新view

-(void)viewWillAppear:(BOOL)animated

{

    [super viewWillAppear:animated];

    tf = (UITextField *)[self.view viewWithTag:];

    tf.text = [AppStatus shareInstance].contextStr;

}

//pop回前一个页面

-(void)doneAction:(id)sender

{

    //单例传值

    [AppStatus shareInstance].contextStr = textField.text;

    [self.navigationController popToRootViewControllerAnimated:YES];

}

6.NSUserDefault传值(顺传倒传都行)

[[NSUSerDefault  standardUserDefaults]setObject:要传的值   forKey:对这个值得标记键];//设置值

[[NSUserDefault  standardUserDefaults]ObjectForKey:根据你的标记键];//获取值

iOS学习之六种传值方式的更多相关文章

  1. iOS学习——页面的传值方式

    一.简述 在iOS开发过程中,页面跳转时在页面之间进行数据传递是很常见的事情,我们称这个过程为页面传值.页面跳转过程中,从主页面跳转到子页面的数据传递称之为正向传值:反之,从子页面返回主页面时的数据传 ...

  2. ios学习-delegate、传值、跳转页面

    ios学习-delegate.传值.跳转页面     1.打开xcode,然后选择ios--Application--Empty Application一个空项目. 项目目录: 2.输入项目名称以及选 ...

  3. ios常见的页面传值方式

    iOS页面间的传值细分有很多种,基本的传值方式有三种:委托Delegate传值.通知NSNotification传值.Block传值,其他在项目中可能会遇到的还有:UserDefault或文件方式传值 ...

  4. iOS的四种传值方式

    传值有四种方法 : 1. 属性传值 2. 单例传值 3. 代理传值 4. block传值     一.属性传值   (前-->后) 1. 后面的界面定义一个属性  存放前一个界面传过来的值    ...

  5. 【转】ios -- ViewController跳转+传值(方式一)

    方式一:通过定义一个实体类传值 (从ViewController1 跳转至 ViewController2) 1.定义实体类NotificationEntity .h声明文件 #import < ...

  6. iOS 学习 - 1.代理传值

    代理的目的是改变或传递控制链.允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针.可以减少框架复杂度.
另外一点,代理可以理解为java中的回调监听机制的一种类似 优点:1.避免子类化带 ...

  7. iOS学习之页面之间传值的方式总结

    传值三种场景: 1.属性传值(从前往后传) 需求:第二个界面标签显示第一个界面输入框文字. 第一步, 在前一个界面定义属性. (语义属性声明为copy); 第二步, 在进入下一个界面之前,给属性传入数 ...

  8. iOS页面传值方式

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

  9. iOS多视图传值方式之通知传值(NSNotification;NSNotificationCenter)

    iOS传值方式之5:通知传值 第一需要发布的消息,再创建NSNotification通知对象,然后通过NSNotificationCenter通知中心发布消息(NSNotificationCenter ...

随机推荐

  1. Linux中/proc目录下文件详解

    转载于:http://blog.chinaunix.net/uid-10449864-id-2956854.html Linux中/proc目录下文件详解(一)/proc文件系统下的多种文件提供的系统 ...

  2. [转]关于 initWithNibName 和 loadNibNamed 的区别和联系

    转载地址:http://jianyu996.blog.163.com/blog/static/1121145552012102293653906/ 关于 initWithNibName 和 loadN ...

  3. 解读HTML 5新语法 提高语义价值

    HTML 5的新标记 设计者们需要完成的任务是要给HTML 5开发一个更丰富的和更有含义的语义,当然可以想象这种新方案将会是很灵活和很高效的,同时与所有的现代互联网标准相适应.下面就是一些将要在HTM ...

  4. 不同系统下的回车\r和换行\n,及其历史

    我们平时按下键盘上的‘回车键’,就能实现回车换行[我们在屏幕上所看到的就是光标移到了下一行的开头位置!!ps:不讨论软件实现的特殊功能,如word里的回车智能缩进].因此对这个按键更准确说应该叫做‘回 ...

  5. 使用异步js解决模态窗口切换的办法

    核心代码 js ="setTimeout(function(){document.getElementsByTagName('Button')[3].click()},100);" ...

  6. hadoop2.0初识1.1

    1.伪分布式hdfs文件系统的搭建(单节点文件系统) 1.1.根据上节的讲解,配置主机映射.jdk和解压hadoop压缩包 1.2.配置namenode 在/opt/modules/hadoop-2. ...

  7. 我的android学习经历34

    用类对象作为ArrayAdapter绑定的基本数据类型(和SimpleAdater效果类似) 一般ArrayAdapter绑定的基本数据类型是String,接下来介绍一下类对象作为基本数据类型: 首先 ...

  8. 【hdu5973】高精度威佐夫博弈

    题意:输入a, b表示两堆石头数目,威佐夫博弈,问:先手胜负? a, b <= 1e100. 高精度.当a > b时, a = (a-b)*黄金分割比 时是先手败状态.因为a, b < ...

  9. VM安装mac及dmg文件转换iso

    今天心血来潮,突然看见一篇关于swift的入门教程,但是前提是有一台mac啊,于是对于屌丝,就只好装黑苹果或者是虚拟机上运行了,但是呢mac貌似听说(没用过)只能在inter上运行,屌丝的本子偏偏是A ...

  10. CSS 3中边框怎么用

    (1)设置边框图片的来源 图片边框默认只在四个顶点显示 none: 无背景图片; border-image-source: url('borderImage.png'); (2)边框图片的分割 将图片 ...