对于C#、Java开发人员来说,肯定都对反射这个概念相当熟悉。所谓反射就是可以动态获取类型、成员信息,同时在运行时(而非编译时)可以动态调用任意方法、属性等行为的特性。
在使用ObjC开发时很少强调其反射概念,因为ObjC的Runtime要比其他语言中的反射强大的多。在ObjC中可以很简单的实现字符串和类型的转换(NSClassFromString()),实现动态方法调用(performSelector: withObject:),动态赋值(KVC)等等。
在Swift中并不提倡使用Runtime,而是像其他语言一样使用反射(Reflect)。当然,目前Swift中的反射还没有其他语言中的反射功能强大,不仅远不及OC的Runtime,离Java的反射也有一定的距离。
Swift的反射机制是基于一个叫 Mirror 的 struct 来实现的,其内部有如下属性和方法:
1
2
3
4
|
let children: Children //对象的子节点。
displayStyle: Mirror . DisplayStyle ? //对象的展示风格
let subjectType: Any . Type //对象的类型
func superclassMirror() -> Mirror ? //对象父类的 mirror
|
4,Swift反射的使用样例
1
2
3
4
5
6
7
|
//用户类 class User {
var name: String = "" //姓名
var nickname: String ? //昵称
var age: Int ? //年龄
var emails:[ String ]? //邮件地址
} |
接着创建一个用户对象,并通过反射获取这个对象的信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//创建一个User实例对象 let user1 = User ()
user1.name = "hangge"
user1.age = 100 user1.emails = [ "hangge@hangge.com" , "system@hangge.com" ]
//将user对象进行反射 let hMirror = Mirror (reflecting: user1)
print ( "对象类型:\(hMirror.subjectType)" )
print ( "对象子元素个数:\(hMirror.children.count)" )
print ( "--- 对象子元素的属性名和属性值分别如下 ---" )
for case let (label?, value) in hMirror.children {
print ( "属性:\(label) 值:\(value)" )
} |
控制台输出信息如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//根据属性名字符串获取属性值 func getValueByKey(obj: AnyObject , key: String ) -> Any {
let hMirror = Mirror (reflecting: obj)
for case let (label?, value) in hMirror.children {
if label == key {
return unwrap(value)
}
}
return NSNull ()
} //将可选类型(Optional)拆包 func unwrap(any: Any ) -> Any {
let mi = Mirror (reflecting: any)
if mi.displayStyle != . Optional {
return any
}
if mi.children.count == 0 { return any }
let (_, some) = mi.children.first!
return some
} |
下面是实际测试样例,同样用上例的User对象做测试:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
//创建一个User实例对象 let user1 = User ()
user1.name = "hangge"
user1.age = 100 user1.emails = [ "hangge@hangge.com" , "system@hangge.com" ]
//通过属性名字符串获取对应的值 let name = getValueByKey(user1, key: "name" )
let nickname = getValueByKey(user1, key: "nickname" )
let age = getValueByKey(user1, key: "age" )
let emails = getValueByKey(user1, key: "emails" )
let tel = getValueByKey(user1, key: "tel" )
print (name, nickname, age, emails, tel)
//当然对于获取到的值也可以进行类型判断 if name is NSNull {
print ( "name这个属性不存在" )
} else if (name as ? AnyObject ) == nil {
print ( "name这个属性是个可选类型,且为nil" )
} else if name is String {
print ( "name这个属性String类型,其值为:\(name)" )
} if nickname is NSNull {
print ( "nickname这个属性不存在" )
} else if (nickname as ? AnyObject ) == nil {
print ( "nickname这个属性是个可选类型,且为nil" )
} else if nickname is String {
print ( "nickname这个属性String类型,其值为:\(nickname)" )
} if tel is NSNull {
print ( "tel这个属性不存在" )
} else if (tel as ? AnyObject ) == nil {
print ( "tel这个属性是个可选类型,且为nil" )
} else if tel is String {
print ( "tel这个属性String类型,其值为:\(tel)" )
} |
控制台输出信息如下:
(注意:正由于KVC是基于Objective-C的,所以其不支持可选类型(optional)的属性,比如上例的 var age:Int?
因此用户类做如下改造:)
1
2
3
4
5
6
7
|
//用户类 class User : NSObject {
var name: String = "" //姓名
var nickname: String ? //昵称
var age: Int = 0 //年龄
var emails:[ String ]? //邮件地址
} |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//创建一个User实例对象 let user1 = User ()
user1.name = "hangge"
user1.age = 100 user1.emails = [ "hangge@hangge.com" , "system@hangge.com" ]
//使用KVC取值 let name = user1.valueForKey( "name" )
let nickname = user1.valueForKey( "nickname" )
let age = user1.valueForKey( "age" )
let emails = user1.valueForKey( "emails" )
//let tel = user1.valueForKey("tel") print (name, nickname, age, emails)
//当然对于获取到的值也可以进行类型判断 if name == nil {
print ( "name这个属性是个可选类型,且为nil" )
} else if name is String {
print ( "name这个属性String类型,其值为:\(name)" )
} if nickname == nil {
print ( "nickname这个属性是个可选类型,且为nil" )
} else if nickname is String {
print ( "nickname这个属性String类型,其值为:\(nickname)" )
} |
1
2
3
4
5
6
7
8
9
|
//创建一个User实例对象 let user1 = User ()
//使用KVC赋值 user1.setValue( "hangge" , forKey: "name" )
user1.setValue(100, forKey: "age" )
user1.setValue([ "hangge@hangge.com" , "system@hangge.com" ], forKey: "emails" )
print (user1.name, user1.nickname, user1.age, user1.emails)
|
原文出自:www.hangge.com 转载请保留原文链接:http://www.hangge.com/blog/cache/detail_976.html
http://www.hangge.com/blog/cache/detail_976.html
Swift - 反射(Reflection)的介绍与使用样例(附KVC介绍)的更多相关文章
-
ArcSDE SDK For Java二次开发介绍、演示样例
在一个工作中,遇到了须要java后台来查询ArcGIS 中用到的Oracle数据库空间数据,因为对ArcGIS空间数据首次接触,仅仅知道Oracle能够使用ST_GEOMETRY字段存储,例如以下图 ...
-
Request介绍及演示样例 PART1
Request在ServletAPI的规范连接地址http://blog.csdn.net/zghwaicsdn/article/details/51035146 HTTP简介 URL是浏览器寻找信息 ...
-
C# 反射(Reflection)技术
本文参考自C#反射(Reflection)详解,纯属学习笔记,加深记忆 在介绍反射前,先介绍一个重要的知识点 .Net应用程序是由程序集(Assembly).模块(Module).类型 ...
-
Java连接redis的使用演示样例
Java连接redis的使用演示样例 Redis是开源的key-value存储工具,redis通经常使用来存储结构化的数据,由于redis的key能够包括String.hash.listset和sor ...
-
通过Canvas及File API缩放并上传图片完整演示样例
创建一个只管的用户界面,并同意你控制图片的大小.上传到server端的数据,并不须要处理enctype为 multi-part/form-data 的情况.只一个简单的POST表单处理程序就能够了. ...
-
Android设计模式之中的一个个样例让你彻底明确装饰者模式(Decorator Pattern)
导读 这篇文章中我不会使用概念性文字来说明装饰者模式.由于通常概念性的问题都非常抽象.非常难懂.使得读者非常难明确究竟为什么要使用这样的设计模式.我们设计模式的诞生,肯定是前辈们在设计程序的时候遇到了 ...
-
Swift - 委托(delegate)的介绍,及使用样例
1,委托的说明 委托(delegate)是Cocoa的一个术语,表示将一个对象的部分功能转交给另一个对象. 比如对象A希望对象B知道将要发生或已经发生某件事情,对象A可以把对象B的引用存为一个实例变量 ...
-
[.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦
[.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...
-
[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程
[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...
随机推荐
-
Centos6 yum安装openldap+phpldapadmin+TLS+双主配置
原文地址:http://54im.com/openldap/centos-6-yum-install-openldap-phpldapadmin-tls-%E5%8F%8C%E4%B8%BB%E9%8 ...
-
Spring实战1:Spring初探
主要内容 Spring的使命--简化Java开发 Spring容器 Spring的整体架构 Spring的新发展 现在的Java程序员赶上了好时候.在将近20年的历史中,Java的发展历经沉浮.尽管有 ...
-
ajax+php+mysql更新
html代码 <input type="button" id="quxiao" class="quxiao" name="q ...
-
PHP获取Cookie模拟登录CURL(转)
要提取google搜索的部分数据,发现google对于软件抓取它的数据屏蔽的厉害,以前伪造下 USER-AGENT 就可以抓数据,但是现在却不行了.利用抓包数据发现,Google 判断了 cookie ...
-
pymssql文档
原文地址 http://pymssql.org/en/latest/ref/_mssql.html _mssql module reference pymssql模块类,方法和属性的完整文档. Com ...
-
【BZOJ1001】狼抓兔子(网络流)
[BZOJ1001]狼抓兔子(网络流) 题面 Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨, ...
-
HTTPS加密那点事-对称、非对称加密、数字证书
转自:[漫画]https 加密那点事 首先,HTTP协议的缺点:没有对数据进行加密,都是明文传输的.如果要改进这种明文传输的协议,该如何做呢? 对称加密: 在每次发送真实数据之前,服务器先生成一把密钥 ...
-
fastjson JSON 对象为空保留null
JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(Object, SerializerFeature.WriteMapN ...
-
bzoj2194 快速傅立叶之二 ntt
bzoj2194 快速傅立叶之二 链接 bzoj 思路 对我这种和式不强的人,直接转二维看. 发现对\(C_k\)贡献的数对(i,j),都是右斜对角线. 既然贡献是对角线,我们可以利用对角线的性质了. ...
-
hibernate框架学习第四天:关联关系、外键、级联等
一对多关联关系表 一方 多方(外键)实体类 一方:TeacherModel 添加多方的集合Set 多方StudentModel 添加一方的对象一方配置关系 name:一方模型中描述多方的集合对象名 c ...