博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS学习之六种传值方式
阅读量:4661 次
发布时间:2019-06-09

本文共 7789 字,大约阅读时间需要 25 分钟。

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 
@class DetailViewController;@protocol PassingValueDelegate
//拟定协议@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:@"123456"]; //页面跳转 }DetailViewController.h 文件引用ViewController的头文件,并添加代理协议如下#import "ViewController.h" @interface TrendViewController : UIViewController
{ } @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 
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 
@interface AppStatus : NSObject{ NSString *_contextStr;}@property(nonatomic,retain)NSString *contextStr;+(AppStatus *)shareInstance;@endAppStatus.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;}@endRootViewController.h#import "RootViewController.h"#import "DetailViewController.h"#import "AppStatus.h" @interface RootViewController () @end @implementation RootViewController -(void)pushAction:(id)sender{ tf = (UITextField *)[self.view viewWithTag:1000]; //单例传值 将要传递的信息存入单例中(共享中) // [[AppStatus shareInstance]setContextStr:tf.text]; 跟下面这种写法是等价的 [AppStatus shareInstance].contextStr = tf.text; //导航push到下一个页面 DetailViewController *detailViewController = [[DetailViewController alloc]init]; //导航push到下一个页面 [self.navigationController pushViewController:detailViewController animated:YES];} @endDetailViewController.h#import
@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(0, 0, 320, 480)]autorelease]; //单例 self.title = [AppStatus shareInstance].contextStr; textField = [[UITextField alloc]initWithFrame:CGRectMake(100, 100, 150, 30)]; 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:1000]; 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:根据你的标记键];//获取值

 

转载于:https://www.cnblogs.com/bzhong/p/5979064.html

你可能感兴趣的文章
C++之命名空间(End Chapter)
查看>>
获取http请求的响应状态
查看>>
【MFC两种视频图像採集方法】DirectShow与Opencv
查看>>
tensorflow中的batch_normalization实现
查看>>
20145219 《信息安全系统设计基础》第05周学习总结
查看>>
C#中隐藏(new)和方法重写(override)和重载(overload)的区别
查看>>
NET Core-学习笔记(三)
查看>>
解决 Unable to load native-hadoop library for your platform
查看>>
eclipse的debug
查看>>
SqlServer 由于未在SqlServer的此实例上安装复制组件解决方法
查看>>
SQLServer (多表左连接,指定操作某几行)
查看>>
在腾讯云服务器上安装JDK+Tomcat并启动tomcat
查看>>
远程连接mysql数据库注意点记录
查看>>
UOJ #206. 【APIO2016】Gap【交互题】
查看>>
Redis cluster的部署
查看>>
Qt编译工程提示qt creator no rule to make target opencv2/core/hal/interface.h need by debug解决方法...
查看>>
27. Remove Element
查看>>
给定一个数组,当中有正负数,求当中的一段“子数组”(即任意长度,连续的数字), 使得这个“子数组”的和是所有“子数组”和中最大的...
查看>>
配置vue环境
查看>>
FluentNhibernate 不支持存储过程
查看>>