[iOS]Swift-反射机制及KVC

Swift中的反射
在Swift中并不提倡使用Runtime,而是像其他语言一样使用反射(Reflect)。当然,目前Swift中的反射还没有其他语言中的反射功能强大,不仅远不及OC的Runtime,离Java的反射也有一定的距离。Swift的反射机制是基于一个叫 Mirror 的 struct 来实现的,其内部有如下属性和方法:
let children: Children //对象的子节点。
displayStyle: Mirror.DisplayStyle? //对象的展示风格
let subjectType: Any.Type //对象的类型
func superclassMirror() -> Mirror? //对象父类的 mirror

原文出自:www.hangge.com 转载请保留原文链接:http://www.hangge.com/blog/cache/detail_976.html*/

import UIKit
class User {
    var name:String = ""
    var nickName:String?
    var age:Int?
    var emails:[String]?
}


let user = User()
user.name = "lixiayi"
user.age = 100
user.emails = ["hangge@hangge.com","system@hangge.com"]

// 将User对象进行反射
let mirror = Mirror(reflecting: user)
print("对象类型:\(mirror.subjectType)")
print("对象子元素的个数:\(mirror.children.count)")
print("--- 对象子元素的属性名和属性值分别如下 ---")
for case let (label?, value) in mirror.children {
    print("属性:\(label)    值:\(value)")
}

// 根据属性名字符串获取属性值
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(any: value)
        }
    }
    return NSNull()
}


func unwrap(any:Any) -> Any {
    let mi = Mirror(reflecting: any)
    if mi.displayStyle != Mirror.DisplayStyle.optional {
        return any
    }

    if mi.children.count == 0 { return any }
    let (_, some) = mi.children.first!
    return some
}


// 创建一个User实例对象
let user1 = User()
user1.name = "hangge"
user1.age = 100
user1.emails = ["hangge@hangge.com","system@hangge.com"]

// 通过属性名字符串获取对应的值
let name = getValueByKey(obj: user1, key: "name")
let nickname = getValueByKey(obj: user1, key: "nickname")
let age = getValueByKey(obj: user1, key: "age")
let emails = getValueByKey(obj: user1, key: "emails")
let tel = getValueByKey(obj: 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是key-value coding的缩写。它是一种间接访问对象的机制。其本质是依据OC中Runtime的强大动态能力来实现的。在Swift中,只要类继承NSObject即可使用KVC。(有一个叫KVO的,它又是基于KVC,大家有兴趣的可以自行研究下。)
 KVC中:key的值就是属性名称的字符串,返回的value是任意类型,需要自己转化为需要的类型。*/

class Teacher:NSObject {
    var name:String = ""  //姓名
    var nickname:String?  //昵称
    var age:Int = 0  //年龄
    var emails:[String]?  //邮件地址
}

//创建一个User实例对象
let t1 = Teacher()
t1.name = "hangge"
t1.age = 100
t1.emails = ["hangge@hangge.com","system@hangge.com"]

//使用KVC取值
let t_name = t1.value(forKey: "name")
let t_nickname = t1.value(forKey: "nickname")
let t_age = t1.value(forKey: "age")
let t_emails = t1.value(forKey: "emails")
//let tel = user1.valueForKey("tel")
print(name, nickname, age, emails)


//当然对于获取到的值也可以进行类型判断
if t_name == nil {
    print("t_name这个属性是个可选类型,且为nil")
}else if t_name is String {
    print("t_name这个属性String类型,其值为:\(t_name)")
}

if t_nickname == nil {
    print("t_nickname这个属性是个可选类型,且为nil")
}else if t_nickname is String {
    print("t_nickname这个属性String类型,其值为:\(t_nickname)")

}

//创建一个Teacher实例对象
let t2 = Teacher()
//使用KVC赋值
t2.setValue("newTeacher", forKey: "name")
t2.setValue(100, forKey: "age")
t2.setValue(["hangge@hangge.com","system@hangge.com"], forKey: "emails")

print(t2.name, t2.nickname, t2.age, t2.emails)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值