iOS——KVC(键值编码)

键值编码(KVC)

KVC(Key Value Coding)是一种允许以字符串形式间接操作对象属性的方式。
最基本的KVC是由NSKeyValueCoding协议提供支持,最基本的操作属性如下:

  • setValue: 属性值 forKey: 属性名:为指定属性设置值;
  • valueForKey: 属性名:获取指定属性的值
    代码演示:

#import <Foundation/Foundation.h>NS_ASSUME_NONNULL_BEGIN@interface AUser : NSObject@property (nonatomic, copy) NSString *str1;
@property (nonatomic, copy) NSString *str2;@endNS_ASSUME_NONNULL_END

#import <Foundation/Foundation.h>
#import "AUser.h"int main(int argc, const char * argv[]) {@autoreleasepool {AUser *aUser = [[AUser alloc] init];//使用KVC方式为str1属性设置值[aUser setValue:@"astr11" forKey:@"str1"];//使用KVC方式为str2属性设置值[aUser setValue:@"astr22" forKey:@"str2"];//使用KVC方式获取AUser对象的属性值NSLog(@"str1: %@", [aUser valueForKey:@"str1"]);NSLog(@"str2: %@", [aUser valueForKey:@"str2"]);}return 0;
}

结果:在这里插入图片描述

在使用KVC时,都是通过字符串来指定被操作的属性。即使用forKey传入属性名的字符串。

对于setValue: forKey: 方法,底层的执行机制如下:

  1. 程序优先考虑调用属性的setter方法
  2. 如果该类没有setter方法,KVC机制会搜索该类中名为传入的“_该字符串”的成员变量(大部分时候即创建属性的时候自动创建的成员变量)无论该成员变量是在接口或者实现部分定义、无论它用哪个访问控制符修饰,这条KVC底层上是对该成员变量的赋值。
    如果该类即没有setter方法也没有“_name”成员变量,那么KVC机制会搜索该类中名为name的成员变量(大部分时候即我们自己定义的成员变量)(与上条一样)
    如果上面3步都没有找到,那么系统会执行该对象的setValue: forUndefinedKey:方法,该方法的实现就是引发一个异常,导致程序结束
    valueForKey方法其他与上面一样,但是它获取的是getter方法的返回值。没有找到成员变量会执行valueForUndefinedKey:方法,该方法也会引起异常导致程序关闭。
    代码举例:

#import <Foundation/Foundation.h>NS_ASSUME_NONNULL_BEGIN@interface AUser : NSObject {@packageNSString *name;NSString *_name;
}@endNS_ASSUME_NONNULL_END

#import "AUser.h"@implementation AUser {int age;
}
@end

#import <Foundation/Foundation.h>
#import "AUser.h"int main(int argc, const char * argv[]) {@autoreleasepool {AUser *aUser = [[AUser alloc] init];//使用KVC给属性赋值,KVC的搜素顺序为://1、setName方法;2、_name成员变量;3、name成员变量//因此,在此处我们是先搜索到了_name成员变量,所以是给_name赋了值,name没有赋值//因此name为空[aUser setValue:@"strName1" forKey:@"name"];NSLog(@"name = %@", aUser->name);NSLog(@"_name = %@", aUser->_name);//虽然age成员变量是在实现部分定义的,但是它还是会被赋值[aUser setValue: [NSNumber numberWithInt:5] forKey:@"age"];NSLog(@"age = %@", [aUser valueForKey:@"age"]);}return 0;
}

处理不存在的Key

前面说过,使用KVC时,如果该属性没有setter、getter方法,也不存在对应的成员变量时,程序会调用setValue: forUndefinedKey:或valueForUndefinedKey:方法。系统默认该方法的实现是引发一个异常然后结束程序,但是我们可以重写这个方法,使其达到我们想要的效果。
只需要在FKApple类实现部分重写setValue:forUndefinedKey:方法,甚至不需要在类接口
声明该方法,例:

#import <Foundation/Foundation.h>NS_ASSUME_NONNULL_BEGIN@interface AUser : NSObject {@packageNSString *name;NSString *_name;
}@endNS_ASSUME_NONNULL_END
#import "AUser.h"- (void) setValue: (id)value forUndefinedKey:(nonnull NSString *)key {NSLog(@"重写了setValue:value forUndefinedKey方法");
}@end
#import <Foundation/Foundation.h>
#import "AUser.h"int main(int argc, const char * argv[]) {@autoreleasepool {AUser *aUser = [[AUser alloc] init];[aUser setValue:@"strName1" forKey:@"1"];NSLog(@"name = %@", aUser->name);NSLog(@"_name = %@", aUser->_name);}return 0;
}

处理nil值

假如我们在一个类中定义两个属性,一个属性是NSString类型的,一个属性是int类型的。当我们给两个属性赋nil值时,NSString属性是可以被赋nil值的,而int类型的值被赋nil时会引发异常,是由于int类型的属性不能接受nil值所导致的。
也就是说,当程序尝试给某个属性设置nil值时,如果该属性并不能接受nil值,那么程序会自动执行该对象的setNilValueForKey:方法。我们同样可以重写该方法来达到我们想要的效果。例如,接下来我们重写该方法,定义一个int类型的属性age,重写该方法使得如果给age属性赋nil值时,就将age赋值为0。代码:

#import "AUser.h"@implementation AUser {int age;
}- (void) setNilValueForKey:(NSString *)key {//如果尝试将key为name的属性设置为nilif ([key isEqualToString:@"age"]) {//将_name设置为0age = 0;} else {//回调父类的setNilValueForKey:执行默认行为[super setNilValueForKey:key];}
}@end
#import <Foundation/Foundation.h>
#import "AUser.h"int main(int argc, const char * argv[]) {@autoreleasepool {AUser *aUser = [[AUser alloc] init];//使用KVC给age属性传nil[aUser setValue: nil forKey:@"age"];NSLog(@"age = %@", [aUser valueForKey:@"age"]);}return 0;
}

结果:在这里插入图片描述

key路径

KVC除了可以操作对象的额属性之外,还可以操作对象的“复合属性”。所谓“复合属性”,KVC机制将其称为key路径。例如:AUser类里面包含着一个BUser类型的bUser属性,bUser对象中又包含着b1属相和b2属性,那么KVC可以通过bUser.b1、bUser.b2这种key路径来支持操作AUser对象的bUser属性的b1和b2属性。
根据key路径设置属性值的方法:

  • setValue: forKeyPath:根据key路径设置属性值
  • valueForKeyPath: 根据key路径获取属性值
    代码示例:
    AUser:
#import <Foundation/Foundation.h>
#import "BUser.h"NS_ASSUME_NONNULL_BEGIN@interface AUser : NSObject {@packageBUser *bUser;
}@property (nonatomic, assign) int aNumber;@endNS_ASSUME_NONNULL_END

BUser:

#import <Foundation/Foundation.h>NS_ASSUME_NONNULL_BEGIN@interface BUser : NSObject@property (nonatomic, copy) NSString *b1;
@property (nonatomic, copy) NSString *b2;@endNS_ASSUME_NONNULL_END
#import <Foundation/Foundation.h>
#import "AUser.h"
#import "BUser.h"int main(int argc, const char * argv[]) {@autoreleasepool {AUser *aUser = [[AUser alloc] init];[aUser setValue:@"12" forKey:@"aNumber"];[aUser setValue:[[BUser alloc] init] forKey:@"bUser"];[aUser setValue:@"这是b1" forKeyPath:@"bUser.b1"];[aUser setValue:@"这是b2" forKeyPath:@"bUser.b2"];NSLog(@"aNumber: %@", [aUser valueForKey:@"aNumber"]);NSLog(@"b1: %@", [aUser valueForKeyPath:@"bUser.b1"]);NSLog(@"b2: %@", [aUser valueForKeyPath:@"bUser.b2"]);}return 0;
}

结果:在这里插入图片描述

实际上,通过KVC操作对象的性能比通过getter、setter方法操作的性能更差,使用KVC的优点是编程更加灵活,更适合提炼一些通用性质的代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/139110.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序之项目基本结构、页面的基础及宿主环境

文章目录 前言一、基本组成结构基本组成小程序页面的组成部分JSON配置文件作用 二、页面基础pagesWXML和HTML的区别WXSS和CSS的区别小程序中js文件分类 三、小程序宿主环境总结 前言 微信小程序的项目基本结构、页面的基础及宿主环境 一、基本组成结构 基本组成 新建一个微信…

迁移 MySQL 数据到 OceanBase 集群

使用 mysqldump 将 mysql的表结构和数据同步到 OceanBase 的MySQL 租户中 Mysql数据库导出 mysqldump -h127.0.0.1 -P3306 -uroot –p --single-transaction --hex-blob --routines --events --triggers --set-gtid-purgedOFF --databases teller >teller.sql mysql> …

网络编程day05(IO多路复用)

今日任务&#xff1a; TCP多路复用的客户端、服务端&#xff1a; 服务端代码&#xff1a; #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <unistd.h> …

网络隔离下实现的文件传输,现有的方式真的安全吗?

在当今的信息化时代&#xff0c;网络安全已经成为了各个企业和机构不可忽视的问题。为了保护内部数据和系统不受外部网络的攻击和泄露&#xff0c;一些涉及国家安全、商业机密、个人隐私等敏感信息的企业和机构&#xff0c;通常会对内外网进行隔离&#xff0c;即建立一个独立的…

Xilinx FPGA 7系列 GTX/GTH Transceivers (4) Aurora 8b10b 递增数收发验证

第一节:Xilinx FPGA 7系列 GTX/GTH Transceivers (1)–了解了GTX硬件的基础知识 第二节:IBERT GTX --通过Ibert IP测试链路通信 第三节:aurora 8b10b single lane 4byte–学习官方历程 递增数验证 自行编写data_gen和data_check 验证aurora 8b10b SFP 1.25G 收发正确。 组…

CentOS在应用程序菜单中创建快捷方式

背景&#xff1a; 在CentOS系统中&#xff0c;安装一些应用软件的时候&#xff0c;我们可能会自定义安装路径&#xff1b;这样在安装完应用程序后&#xff0c;在“Application”下&#xff0c;可能找不到对应的快捷键&#xff1b;这是就需要手动去创建跨界方式。 应用&#xf…

CNN(九):Inception v3算法实战

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 1 理论基础 Inception v3论文 Inception v3由谷歌研究员Christian Szegedy等人在2015年的论文《Rethinking the Inception Architecture f…

ubuntu samba文件共享服务器搭建

目的&#xff1a; 为了实现Android源码在ubuntu的编译&#xff0c;在windows上进行源码的修改和验证&#xff0c;需要在ubuntu系统上搭建共享文件夹&#xff0c;这里将ubuntu的/home/用户/路径下的所有内容共享&#xff0c;方法如下 ubuntu端&#xff1a; 一、samba安装 sud…

【暴力DP】CF1409 F

Problem - F - Codeforces 题意&#xff1a; 思路&#xff1a; 首先有个很明显的结论是&#xff1a;替换的字符一定是那两个字符之一 那么替换成哪个字符贡献更大不确定&#xff0c;因此考虑DP 因为有操作次数限制&#xff0c;直接把操作放进状态里 为了计算贡献&#xff…

机器学习第十一课--K-Means聚类

一.聚类的概念 K-Means算法是最经典的聚类算法&#xff0c;几乎所有的聚类分析场景&#xff0c;你都可以使用K-Means&#xff0c;而且在营销场景上&#xff0c;它就是"King"&#xff0c;所以不管从事数据分析师甚至是AI工程师&#xff0c;不知道K-Means是”不可原谅…

spring:实现初始化动态bean|获取对象型数组配置文件

0. 引言 近期因为要完成实现中间件的工具包组件&#xff0c;其中涉及要读取对象型的数组配置文件&#xff0c;并且还要将其加载为bean&#xff0c;因为使用了spring 4.3.25.RELEASE版本&#xff0c;很多springboot的相关特性无法支持&#xff0c;因此特此记录&#xff0c;以方…

Mac配置iTerm样式终端

一、MacOs系统 MacOs中终端使用iTerm2 1. 配置oh-my-zsh oh my zsh 的地址&#xff1a; https//github.com/ohmyzsh/ohmyzsh 插件存放位置&#xff1a;~/.oh-my-zsh/plugins 下载常用的插件 git clone http://github.com/zsh-users/zsh-syntax-highlighting.git 修改配…

怎么将几张图片做成pdf合在一起

怎么将几张图片做成pdf合在一起&#xff1f;在我们平时的工作中&#xff0c;图片和pdf都是非常重要的电脑文件&#xff0c;使用也非常频繁&#xff0c;图片能够更为直观的展示内容&#xff0c;而pdf则更加的正规&#xff0c;很多重要文件大多会做成pdf格式的。在职场人的日常工…

TypeError: res.data.map is not a function微信小程序报错

从数据库查&#xff1a; 调用的是&#xff1a; 访问的springboot后端是这个&#xff1a; 打印出来如下&#xff1a; 看到是json格式的数据 [Users [id3, name刘雨昕, phone18094637788, admintrue, actionsJsonadmin, createAtSat Sep 16 10:11:20 CST 2023, tokentest], User…

深入了解队列数据结构:定义、特性和实际应用

文章目录 &#x1f34b;引言&#x1f34b;队列的定义&#x1f34b;队列的实现&#x1f34b;队列的应用&#x1f34b;练习题&#x1f34b;结语 &#x1f34b;引言 队列&#xff08;Queue&#xff09;是计算机科学中一种重要的数据结构&#xff0c;它常用于各种应用程序中&#x…

拼多多API接口解析,实现根据ID取商品详情

拼多多是一个流行的电商平台&#xff0c;它提供了API接口供开发者使用。要根据ID获取商品详情&#xff0c;您需要使用拼多多API接口并进行相应的请求。 以下是使用拼多多API接口根据ID获取商品详情的示例代码&#xff08;使用Python编写&#xff09;&#xff1a; import requ…

​专业图像处理软件 Photoshop 2023 mac版本更新(ps2023中文)

​Photoshop 2023 mac是一款图像编辑和图形设计软件&#xff0c;广泛应用于专业人士和爱好者。它提供了许多工具和功能&#xff0c;用于创建、编辑和增强数字图像&#xff0c;包括图层、蒙版、滤镜和各种选择工具。Photoshop还支持多种文件格式&#xff0c;包括psD、JPEG、PNG和…

全套办公软件Office 2019 mac专业版功能

Microsoft office 2019 Beta for Mac 是一款办公软件套装&#xff0c;它包含常用的办公应用程序&#xff0c;如 Word、Excel、PowerPoint 和 Outlook 等。office 2019 Beta 版本是一个测试版本&#xff0c;旨在让用户提前体验下一个版本的 office 套件&#xff0c;以便用户可以…

全国职业技能大赛云计算--高职组赛题卷③(私有云)

全国职业技能大赛云计算--高职组赛题卷③&#xff08;私有云&#xff09; 第一场次题目&#xff1a;OpenStack平台部署与运维任务1 基础运维任务&#xff08;5分&#xff09;任务2 OpenStack搭建任务&#xff08;15分&#xff09;任务3 OpenStack云平台运维&#xff08;15分&am…

2023!6招玩转 Appium 自动化测试

Appium是个什么鬼 Appium是一个移动端的自动化框架&#xff0c;可用于测试原生应用&#xff0c;移动网页应用和混合型应用&#xff0c;且是跨平台的。可用于IOS和Android以及firefox的操作系统。原生的应用是指用android或ios的sdk编写的应用&#xff0c;移动网页应用是指网页…