iOS 页面传值方法汇总
来源:互联网 发布:mac文件批量重命名 编辑:程序博客网 时间:2024/06/05 00:51
方法汇总
1、属性
2、方法
3、Delegate代理
4、Block回调
5、通知
6、KVO
7、单例
8、NSUserDefault(等本地化手段)
几种方式有着各自应用的场景,各有各的优点和缺点。
一、属性传值
使用场景:AtoB
说明:这种方式通常需要B对象,在A中设置B的属性,达到传值的目的。
使用:
在B中声明属性:
@property (copy ,nonatomic) NSString *value;
在A中修改B的属性
BCtrl *ctrl = [[BCtrl alloc] initWithNibName:@"BCtrl" bundle:nil];ctrl.value = @"LOLITA";[self.navigationController pushViewController:ctrl animated:YES];
这样在B中就可以使用这个value了。
二、方法传值
使用场景:AtoB
说明:这种方式也需要B对象,在A中调用B的方法并将数据传递给B
使用:
在B中声明方法
-(void)passValue:(NSDictionary *)dic;
在A中调用B的方法
[B_Object passValue:@{@"name":@"LOLITA"}];
B中使用传递过来的数据
-(void)passValue:(NSDictionary *)dic{ NSLog(@"%@",dic);}
效果:
使用场景:BtoA
说明:思路跟AtoB一样,使用A对象调用其方法传递数据
首先在A中定义传值方法并实现该方法
.h 文件中 声明该方法@interface ACtrl : UIViewController-(void)passValue:(NSDictionary *)dic; // 传值方法@end.m 文件中 实现该方法-(void)passValue:(NSDictionary *)dic{ // 使用传递过来的字典 NSLog(@"%@",dic);}
在B中声明一个id类型属性
@property (weak ,nonatomic) id delegate; // 用来获得A对象,注意不要引起循环引用,我这里使用了weak
在A中初始化B的时候将A对象传递给B的这个属性
BCtrl *ctrl = [[BCtrl alloc] initWithNibName:@"BCtrl" bundle:nil];ctrl.delegate = self; // 指向id属性[self.navigationController pushViewController:ctrl animated:YES];
在B的某个特定事件下(如返回),调用A的传值方法将数据传递过去
- (IBAction)goBackBtn:(UIButton *)sender { // 返回事件 if (self.delegate&&[self.delegate respondsToSelector:@selector(passValue:)]) { [self.delegate passValue:@{@"name":@"LOLITA",@"age":@"24"}]; //传递数据 } [self.navigationController popViewControllerAnimated:YES];}
这时候,A中的传值方法被调用,输出了B传过来的数据
在上面这个例子中,有人发现这样的使用和delegate很像,没错,delegate本来就是某个对象委托去达到某个目的而产生的设计模式,我这里使用A的传值方法来完成传值功能,那么我们iOS的设计模式中,完全可以将部分业务功能抽离出来,赋予代理,让其去实现这种功能。
三、Delegate代理传值
使用场景:BtoA
说明:代理模式是我们常用的设计模式,常用来委托完成某些业务功能,我们这里仅用来传递数据
首先我们新建一个协议文件,赋予其某种功能
#import <Foundation/Foundation.h>@protocol PageDelegateProtocol <NSObject>// 这里没有实现,只有方法声明,有些类似java中的接口-(void)passValue:(NSDictionary *)dic; // 具有传值功能的方法@end
在B中导入该协议,并新建代理对象作为其属性
#import "PageDelegateProtocol.h"@interface BCtrl : UIViewController@property (nonatomic,weak) id <PageDelegateProtocol> delegate; // 代理对象@end
在B的某个特定事件下(如返回),将数据传递给A
- (IBAction)goBackBtn:(UIButton *)sender { if (self.delegate&&[self.delegate respondsToSelector:@selector(passValue:)]) { //使用协议中的传值方法 [self.delegate passValue:@{@"name":@"LOLITA",@"age":@"24"}]; } [self.navigationController popViewControllerAnimated:YES];}
在A中,将A对象指向B中的代理
BCtrl *ctrl = [[BCtrl alloc] initWithNibName:@"BCtrl" bundle:nil];ctrl.delegate = self;[self.navigationController pushViewController:ctrl animated:YES];
A中遵守协议,并实现协议方法
-(void)passValue:(NSDictionary *)dic{ NSLog(@"%@",dic);}
这样我们就使用了代理实现了页面的传值,我们可以通过和BtoA的方法传值方式的对比来理解代理的方式
四、Block回调传值
block可以作为属性传值、也可以作为参数传值
1、block作为属性来传值
使用场景:BtoA
使用:
首先在B页面声明一个block作为属性
typedef void(^passValue)(NSDictionary *dic); // 声明一个block@interface ACtrl : UIViewController@property (nonatomic,copy) passValue passDic; // 作为B的属性@end
在特定事件(如返回事件)使用block回调
- (IBAction)goBackBtn:(UIButton *)sender { if (self.passDic) { self.passDic(@{@"name":@"LOLITA",@"age":@"24",@"sex":@"male"}); // 回调数据 } [self.navigationController popViewControllerAnimated:YES];}
在A中,实现block回调函数
BCtrl *ctrl = [[BCtrl alloc] initWithNibName:@"BCtrl" bundle:nil];ctrl.passDic = ^(NSDictionary *dic) { // 实现block NSLog(@"%@",dic); };[self.navigationController pushViewController:ctrl animated:YES];
2、block作为参数来传值
使用场景:BtoA
说明:这种方式在请求类中比较常见,在请求回来数据之后使用block回调数据,这里使用两个页面简单介绍使用过程
先在B类中,定义一个block
typedef void(^passValue)(NSDictionary *dic);
将bock作为参数声明一个方法
-(void)passDic:(passValue)dicBlock;
实现该方法
-(void)passDic:(passValue)dicBlock{ if (dicBlock) { // 使用block回调数据 dicBlock(@{@"name":@"LOLITA",@"age":@"24"}); }}
在A类中,使用B类调用带block参数的方法
BCtrl *ctrl = [[BCtrl alloc] initWithNibName:@"BCtrl" bundle:nil];[ctrl passDic:^(NSDictionary *dic) { NSLog(@"--%@",dic);}];
五、通知传值
使用场景:Ato多个页面
说明:通知属于观察者模式,属于一对多的传递消息,相比于代理和block的一对一,通知的开销较大,所有只有在需要将消息传递给多个页面的时候再使用通知,另外通知属于单例
使用:
在需要接收通知消息的页面添加注册
// 给self添加通知事件,当name和发送方相同的时候才能接受到消息[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getUserInfo:) name:@"passValue" object:nil];// 处理消息的方法-(void)getUserInfo:(id)userInfo{ NSLog(@"%@",userInfo);}
传递消息的页面,特定的事件发送通知(如返回)
- (IBAction)goBackBtn:(UIButton *)sender { [self.navigationController popViewControllerAnimated:YES]; [[NSNotificationCenter defaultCenter] postNotificationName:@"passValue" object:nil userInfo:@{@"name":@"LOLITA",@"sex":@"male"}];}
是不是非常方便呢?还需要注意的是:1、注册通知一定要在发送通知的代码执行之前 2、通知需要手动移除
// 在添加监听的页面移除通知,这里移除了name为passValue的通知,也可以不区分name全部移除-(void)dealloc{ [[NSNotificationCenter defaultCenter] removeObserver:self name:@"passValue" object:nil];}
六、KVO (Key-Value Observing)键值观察
KVO顾名思义键值对观察,它通过监听被观察者的某些属性值的变化而响应某些事件,也是一种消息传递。
为了演示,我给B页面设置一个属性,作为被观察的属性
@interface BCtrl : UIViewController@property (assign ,nonatomic) NSInteger value;@end
使用:
首先,被观察者需要为自己被监听的属性添加监听事件,B是被观察者
// A页面中- (IBAction)btn:(UIButton *)sender { BCtrl *ctrl = [[BCtrl alloc] initWithNibName:@"BCtrl" bundle:nil]; // self是A页面,它监听B页面的value属性 ,options有多种,这里获取新值 [ctrl addObserver:self forKeyPath:@"value" options:NSKeyValueObservingOptionNew context:@"changeValue"]; [self.navigationController pushViewController:ctrl animated:YES];}
观察者A,需要实现observeValueForKeyPath:ofObject:change:context:方法,来获取监听属性的变化
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if (context == @"changeValue") { if ([keyPath isEqualToString:@"value"]) { NSLog(@"%@",change); // 记得要移除观察者 [object removeObserver:self forKeyPath:@"value"]; } } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; }}
这样当被观察者B的value属性发生变化时,A就可以得到消息并获取相应的值
- (IBAction)goBackBtn:(UIButton *)sender { [self.navigationController popViewControllerAnimated:YES]; self.value = 10;}
效果
以上方法都是明确知道被传递的对象是谁,要做什么,属于一种消息的传递,是事件响应(属性传值可以通过重写setter方法来实现事件的响应),但是单例和NSUserDefault不同,它们不像代理明确需要做什么,也不像通知可以传递消息,仅仅被用来存储和获取数据,并且,它们不知道谁存储的数据,也不知道谁来调用,这些事情需要我们自己主动去做。
七、单例
单例即在app生命进程中仅被初始化一次,它的内存地址在初始化时就确定了,所以我们可以在A页面存储数据,B页面取数据,并且值是相同的
注意:当app生命进程结束后,单例的内存空间也被释放了,数据会消失掉
使用:
首先我们需要新建单例对象
.h 文件#import <Foundation/Foundation.h>@interface DataManager : NSObject@property (strong ,nonatomic) NSDictionary *dic; // 存储的数据+(instancetype)shareDataManager; // 初始化方法@end
.m 文件+(instancetype)shareDataManager{ static dispatch_once_t onceToken; static DataManager *manager; dispatch_once(&onceToken, ^{ manager = [DataManager new]; }); return manager;}
使用单例存数据,在需要的地方导入单例文件
// 存储一个字典数据[DataManager shareDataManager].dic = @{@"name":@"LOLITA",@"iOS":@"2"};
在需要取数据的地方
NSLog(@"%@",[DataManager shareDataManager].dic);
效果
八、NSUserDefault等本地化手段
NSUserDefault是使用KVC手段访问、修改数据,并会在本地持久化
存储数据:通过不同的key来存数据
[[NSUserDefaults standardUserDefaults] setObject:@"LOLITA" forKey:@"name"];[[NSUserDefaults standardUserDefaults] synchronize];
获取数据:key要相同
[[NSUserDefaults standardUserDefaults] objectForKey:@"name"]
删除数据:
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"name"];
单例和NSUserDefault操作数据比较
单例的存储的数据在app结束时就消失了,NSUserDefaults属于本地化存储,存储的数据只要app不删除,就一直存在,所以在使用这两种方式存取数据时要根据业务需求来。
九、总结
自己体会吧。。。啊哈哈哈
- iOS 页面传值方法汇总
- ASP.NET 页面传值方法汇总
- asp.net页面传值方法汇总
- asp.net页面传值方法汇总
- asp.net页面传值方法汇总
- asp.net页面传值方法汇总
- asp.net页面传值方法汇总
- asp.net页面传值方法汇总
- asp.net页面传值方法汇总
- asp.net页面传值方法汇总
- IOS 页面跳转传值方法总结
- IOS 页面传值的方法
- 页面刷新方法汇总
- 页面刷新方法汇总
- 页面间传值方法汇总
- 页面刷新方法汇总
- php抓取页面方法汇总
- php抓取页面方法汇总
- JS对象属性
- Android通过文件类型打开系统已有支持程序开启
- 如何构建 FinTech 科学反欺诈体系|架构师实践日
- HTML
- redis数据库
- iOS 页面传值方法汇总
- 基于深度学习的Person Re-ID(综述)
- 文件过滤器
- topgp登陆不了提示DVM connection timed out
- 【Spring】Spring高级话题-计划任务-@EnableScheduling
- ElasticSearch5.2.2 安装
- Airbnb欺诈预测机器学习模型设计:准确率和召回率的故事 发表于2015-07-15 16:14| 3926次阅读| 来源AirBNB/Data| 1 条评论| 作者Ariana Radianto
- 基于深度学习的Person Re-ID(特征提取)
- sqlserver2008R2数据导入还原的经历