美文网首页
深度探究HandyJSON(六) KVC

深度探究HandyJSON(六) KVC

作者: Lin__Chuan | 来源:发表于2018-12-27 00:24 被阅读19次

书接上文. 这篇文章的代码依然是我根据实际情况将功能进行拆分的代码.

既然我们已经能够为属性在内存中赋值, 那么 KVC 中的 setValue 已经完成了. 我们来看看代码实现.

第 1 步: 获取包装好的属性列表

func properties(_ type: Any.Type) -> [PropertyDescription] {
    let hashedType = HashedType(type)
    if let properties = cachedProperties[hashedType] {  // 有缓存直接取值
        return properties
    } else {  // 取得包装好的属性, 并设置缓存
        
        let properties = propertyDescriptions
        cachedProperties[hashedType] = properties
        return properties
    }
}

// property 缓存
struct HashedType : Hashable {
    let hashValue: Int
    init(_ type: Any.Type) {
        hashValue = unsafeBitCast(type, to: Int.self)
    }
    init<T>(_ pointer: UnsafePointer<T>) {
        hashValue = pointer.hashValue
    }
}

func == (lhs: HashedType, rhs: HashedType) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

var cachedProperties = [HashedType : Array<PropertyDescription>]()

我们可以通过 Type 来获取属性列表, 这里通过哈希表做了缓存, 避免同一类型的属性重复获取属性, 算是一种优化.

第 2 步: 为属性对应的内存赋值 - 工具类

extension AnyExtensions {
    // 获取值
    public static func value(from storage: UnsafeRawPointer) -> Any {
        return storage.assumingMemoryBound(to: self).pointee
    }
}

func extensions(of value: Any) -> AnyExtensions {
    struct Extensions : AnyExtensions {}
    var extensions: AnyExtensions = Extensions()
    withUnsafePointer(to: &extensions) { pointer in
        UnsafeMutableRawPointer(mutating: pointer).assumingMemoryBound(to: Any.self).pointee = value
    }
    return extensions
}

第 3 步: 最终赋值

func set<T>(_ value: Any, key: String, for instance: inout T) {
    if let property = properties(T.self).first(where: { $0.key == key }) {
        
        let propAddr = rawPointer.advanced(by: property.offset)
        extensions(of: property.type).write(value, to: propAddr)
    }
}

接下来主要思考的是怎么获取到值. getValue 有两种思路:

  • 利用反射机制, 通过 Mirror 来获取到属性值.
  • 直接从内存中取值.

第一种方式比较简单, 但是和我们之前的代码相差比较大, 我们完全可以和之前的代码进行统一, 直接从内存中取值.

第 1 步: 将实例的所有属性名字和内容进行包装

struct Property {
    let key: String
    let value: Any
}

func properties(_ instance: Any) -> [Property] {
    let props = properties(type(of: instance))
    return props.map {
        let propAddr = rawPointer.advanced(by: $0.offset)
        let value = extensions(of: $0.type).value(from: propAddr)
        return Property(key: $0.key, value: value)
    }
}

第 2 步: 通过包装属性内容的数组, 查找目标属性名, 得出结果

func get(_ key: String, from instance: Any) -> Any {
    let any = properties(instance).first(where: { $0.key == key })?.value
    guard let value = any else {
        return 0
    }
    return value
}

测试

struct Person {
    var isBoy: Bool = true
    var age: Int = 0
    var height: Double = 130.1
    var name: String = "jack"
}

class PersonClass {
    var isBoy: Bool = true
    var age: Int = 0
    var height: Double = 130.1
    var name: String = "jack"
}

// 测试 KVC
set(200, key: "age", for: &personClass)
print(personClass.age) // 设置成功
print(get("age", from: personClass))

set(200, key: "age", for: &personStruct)
print(personStruct) // 设置成功
print(get("age", from: personStruct))

或许这里的代码并不健壮, 但可以作为 Swift 中的 KVC 的一种参考.

相关文章

  • 深度探究HandyJSON(六) KVC

    书接上文. 这篇文章的代码依然是我根据实际情况将功能进行拆分的代码. 既然我们已经能够为属性在内存中赋值, 那么 ...

  • 深度探究HandyJSON(四) 解析 struct

    在这个系列的前两篇文章中, 我们讲了 Swift指针的使用, Mirror 的原理, 这些其实都是为接下来的几篇文...

  • 深度探究HandyJSON(五) 解析 class

    书接上文, class 和 struct 还是有些不同. 回顾一下, 如何在内存上为实例的属性赋值呢? 获取到属性...

  • 深度探究HandyJSON(二) Mirror 的原理

    在上一篇文章中, 我着重介绍了 Swift中指针的使用, 这篇文章主要围绕以下几点: HandyJSON 的优势....

  • 深度探究HandyJSON(三) 再探内存

    在这个系列的第一篇文章里我们介绍了 Swift中指针的使用. 这篇文章会继续探究对象在内存中的分布. 问题再现 ...

  • 深度探究HandyJSON(一) Swift 指针的使用

    为了避免疏漏, 我从官方文档作了截图, 苹果官网文档1 , 文档2 本文概要 按照官方文档, 介绍Swift中的指...

  • NSRunLoop

    深入理解RunLoop RunLoop深度探究(一) RunLoop深度探究(二) RunLoop深度探究(三) ...

  • 探究KVC本质

    细致的看了下KVC的东西,记录一下。 KVC:key-value-coding,键值编码。 KVC可以干什么?利用...

  • KVC原理探究

    KVC iOS在实际开发过程中用KVC的地方也是不少的,但是很少有时间探究里面涵盖的内容,网上的一些文章也纯属是翻...

  • KVO-KVC的原理探究 - KVC篇

    关于KVC的探究 基本介绍和使用 KVC全称Key-Value Coding 键值编码,可以通过Key来访问某个属...

网友评论

      本文标题:深度探究HandyJSON(六) KVC

      本文链接:https://www.haomeiwen.com/subject/yqkklqtx.html