iOS中KVC与KVO的应用解析

本文涉及的产品
云解析DNS,个人版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: iOS中KVC与KVO的应用解析

iOS中KVC与KVO的应用解析


一、NSKeyValueCoding(KVC)


1、从一个小例子引入


KVC键值编码是Object-C为我们提供的一种对成员变量赋值的方法。在探讨其方法之前,我们先来看一个小例子:


首先,创建一个数据模型model类:


//.h文件

#import <Foundation/Foundation.h>

@interface Model : NSObject

{

   @public//将成员变量设置为公有的 以便其他文件有访问权限

   NSString * str;

}

@end

我们在其他文件中有两种方法str进行赋值和取值:


   Model * model = [[Model alloc]init];

   model->str=@"312";//普通方法赋值

   [model setValue:@"321" forKey:@"str"];//kvc赋值

   NSLog(@"%@",model->str);//普通方法取值

   NSLog(@"%@",[model valueForKey:@"str"]);//kvc取值

同样的,对于用@property声明的变量,使用kvc的效果和使用点语法,setter,getter方法的效果是一样的。


2、KVC有关函数方法详解


通过上面的例子,我们已经可以简单了解KVC是干什么的了,下面是一些常用方法。


+ (BOOL)accessInstanceVariablesDirectly;


这个方法类似一个开关,默认返回为YES,表示支持KVC方式赋值,也可以在子类中将其重写,如果返回为NO,则再进行KVC会抛出异常。


- (id)valueForKey:(NSString *)key;


通过键取值


- (void)setValue:(id)value forKey:(NSString *)key;


通过字符串键给成员变量赋值


- (BOOL)validateValue:(inout id *)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;


系统默认实现的方法,验证一个键值是否有效


- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;


将取到的值放入一个可变数组中


- (NSMutableOrderedSet *)mutableOrderedSetValueForKey:(NSString *)key NS_AVAILABLE(10_7, 5_0);


将取到的值放入可变的有序集合中


- (NSMutableSet *)mutableSetValueForKey:(NSString *)key;


将取到的值放入可变的集合中


- (id)valueForKeyPath:(NSString *)keyPath;

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;


上面这两个方法分别是通过路径赋值与取值,数据结构类似地图,比如在model类中有一个成员变量model2,在Model2类中有一个字符串,我们可以通过如下的方式赋值取值


//Model.h

#import "Model2.h"

@interface Model : NSObject

{

   @public

   NSString * str;

   Model2 * model2;

}

//Model2.h

@interface Model2 : NSObject

{

@public

   NSString * str2;

}

@end

//其他文件

   Model * model = [[Model alloc]init];

   Model2 * model2 = [[Model2 alloc]init];

   model->model2=model2;

   [model setValue:@"123" forKeyPath:@"model2.str2"];

   NSLog(@"%@",[model valueForKeyPath:@"model2.str2"]);


- (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath;

- (NSMutableOrderedSet *)mutableOrderedSetValueForKeyPath:(NSString *)keyPath NS_AVAILABLE(10_7, 5_0);

- (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath;


上面三个方法与前面类似,只是是从路径取值的。


- (id)valueForUndefinedKey:(NSString *)key;


这个方法可以获取没有提前定义的成员变量的值,比如运行时创建的,下面这个方法是给未定义的成员变量赋值


- (void)setValue:(id)value forUndefinedKey:(NSString *)key;


注意:这两个方法默认的实现会抛出异常,子类必须重写才能使用。


- (void)setNilValueForKey:(NSString *)key;


将成员变量置为nil


- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;


根据键值获取键值对字典


- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;


通过字典对成员变量同意赋值,经常使用


二、NSKeyValueObservingCustomization(KVO)


KVO是一种消息监听机制,可以在某个量发生变化的时候将消息传送给监听者,因此广泛用于传值,界面低耦合等逻辑中。KVO机制的核心是以下三个方法:


- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;


使用这个方法注册一个监听者,参数解释如下:


observer:监听者对象


keyPath:监听的参数


options:监听选项


context:参数传递


监听的选项枚举如下:


typedef NS_OPTIONS(NSUInteger, NSKeyValueObservingOptions) {

   NSKeyValueObservingOptionNew = 0x01,//回调的字典中存放新值

   NSKeyValueObservingOptionOld = 0x02,//回调的字典中存放旧值

   NSKeyValueObservingOptionInitial ,//值改变前进行回调

   NSKeyValueObservingOptionPrior//改变前后都进行回调


};

//回调字典后面会解释


- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context ;

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;


这两个方法都是用来移除监听者


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;


这个方法是监听对象数据改变时回调的方法,change是一个字典,字典中根据监听的选项不同,存放不同的值(新或者旧)。context是传递的参数。


代码示例:


- (void)viewDidLoad {

   [super viewDidLoad];

   // Do any additional setup after loading the view, typically from a nib.

    model = [[Model alloc]init];

   //添加监听者

   [model addObserver:self forKeyPath:@"str" options:NSKeyValueObservingOptionNew context:@"321"];

   [model setValue:@"qw" forKey:@"str"];

}


- (void)didReceiveMemoryWarning {

   [super didReceiveMemoryWarning];

   // Dispose of any resources that can be recreated.

}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{

   if ([keyPath isEqualToString:@"str"]) {

       NSLog(@"%@",context);

   }

}

目录
相关文章
|
8天前
|
Java 开发工具 Android开发
安卓与iOS开发差异解析
【6月更文挑战第21天】本文旨在深入探讨安卓和iOS两大移动操作系统在应用开发过程中的主要差异。通过对比分析,揭示各自的设计哲学、编程语言选择、用户界面构建、性能优化策略以及发布流程的异同。文章将提供开发者视角下的实用信息,帮助他们更好地理解各自平台的特点和挑战,从而做出更明智的开发决策。
|
19天前
|
搜索推荐 Android开发 iOS开发
深入解析安卓与iOS操作系统的异同
安卓和iOS是目前两大主流移动操作系统,它们分别代表了开放性和封闭性的设计理念。本文将从系统架构、用户界面、应用生态等方面深入探讨安卓和iOS之间的异同,帮助读者更好地理解这两个操作系统的特点和优势。
39 3
|
2月前
|
前端开发 JavaScript 程序员
HBuilderX使用mac打包ios应用提示苹果根证书没有安装
HBuilderX使用mac打包ios应用提示苹果根证书没有安装
26 0
|
2月前
|
安全 Swift iOS开发
【Swift 开发专栏】Swift 与 UIKit:构建 iOS 应用界面
【4月更文挑战第30天】本文探讨了Swift和UIKit在构建iOS应用界面的关键技术和实践方法。Swift的简洁语法、类型安全和高效编程模型,加上与UIKit的紧密集成,使开发者能便捷地创建用户界面。UIKit提供视图、控制器、布局、动画和事件处理等功能,支持灵活的界面设计。实践中,遵循设计原则,合理组织视图层次,运用布局和动画,以及实现响应式设计,能提升界面质量和用户体验。文章通过登录、列表和详情界面的实际案例展示了Swift与UIKit的结合应用。
|
2月前
|
定位技术 开发工具 iOS开发
ios9定位服务的app进入后台三分钟收不到经纬度,应用被挂起问题及解决方案
ios9定位服务的app进入后台三分钟收不到经纬度,应用被挂起问题及解决方案
25 0
|
2月前
|
存储 Swift iOS开发
使用Swift开发一个简单的iOS应用的详细步骤。
使用Swift开发iOS应用的步骤包括:创建Xcode项目,设计界面(Storyboard或代码),定义数据模型,实现业务逻辑,连接界面和逻辑,处理数据存储(如Core Data),添加网络请求(必要时),调试与测试,根据测试结果优化改进,最后提交至App Store或其它平台发布。
61 0
|
2月前
|
存储 安全 Swift
【Swift 开发专栏】使用 Swift 开发一个简单的 iOS 应用
【4月更文挑战第30天】本文介绍了使用 Swift 开发简单 iOS 待办事项应用的步骤。首先,阐述了 iOS 开发的吸引力及 Swift 语言的优势。接着,详细说明了应用的需求和设计,包括添加、查看和删除待办事项的功能。开发步骤包括创建项目、界面搭建、数据存储、功能实现,并提供了相关代码示例。最后,强调了实际开发中需注意的细节和优化,旨在帮助初学者掌握 Swift 和 iOS 开发基础。
|
2月前
|
搜索推荐 API iOS开发
利用SwiftUI构建动态iOS天气应用
【4月更文挑战第23天】 在本文中,我们将探讨如何使用SwiftUI框架实现一个动态的iOS天气应用程序。将重点介绍如何通过集成第三方天气API、设计响应式用户界面以及应用数据绑定技术来增强用户体验。我们的目标是创建一个能够根据当前位置实时更新天气信息的应用,并确保其界面简洁、易用且美观。
30 0
|
9天前
|
机器学习/深度学习 缓存 算法
netty源码解解析(4.0)-25 ByteBuf内存池:PoolArena-PoolChunk
netty源码解解析(4.0)-25 ByteBuf内存池:PoolArena-PoolChunk

推荐镜像

更多