美文网首页iOS成长之路
Swift 中的 @dynamicMemberLookup注解

Swift 中的 @dynamicMemberLookup注解

作者: liaoworkinn | 来源:发表于2020-04-17 13:10 被阅读0次

    什么是 @dynamicMemberLookup

    字面意思来理解就是动态成员查找, 简单理解其目的就是动态来获取属性的值。

    // 注解要使用的类或者结构体支持动态成员查找
    @dynamicMemberLookup
    struct Worker {
        // 必须要实现的方法。返回值类型可自定义
            subscript(dynamicMember member: String) -> String {
                let properties = ["name": "LiaoWorking", "city": "Shanghai"]
                return properties[member, default: ""]
            }
    }
     
    let worker = Worker()
    let name = worker.name    // liaoworking
    

    看到这里你肯定会一脸黑人问号❓❓❓
    Worker没有name这个属性 我为什么会取到name的值。
    难道编译器就不检查一下么。
    这里编译器的确就管都不管一下了。 dynamiclookup这两个词的意思马上就体现出来了。动态去查找

    Demo中当执行下面这行代码时

    let name = worker.name 
    

    实际上调用了我们实现的subscript方法,把name当”name”参数传递进去。 所以就得到了 name 为 liaoworking的结果。

    下面再来看看关于@dynamicMemberLookUp更多的使用方法。

    1. 多类型的返回
        // 注解说明要使用的类或者结构体支持动态成员查找   
        @dynamicMemberLookup
        struct Worker {
            // 返回值为String
                subscript(dynamicMember member: String) -> String {
                    let properties = ["age": "17"]
                    return properties[member, default: ""]
                }
                // 返回值为Int
                 subscript(dynamicMember member: String) -> Int {
                    let properties = ["age": 18]
                    return properties[member, default: -1]
                }
                
        }
         
        let worker = Worker()
        // 这里系统可根据类型判断 来调用不同的subscript实现
        let ageString: String = worker.age    // “17”
        let ageInt: Int = worker.age //19
    

    上面的Demo具体使用场景还不太明确,只是有这样的用法。这里提一下。

    1. 下面这个Demo就很能说明@dynamicMemberLookup 的一个有用场景。
      我们来创建一个JSON解析Struct
        @dynamicMemberLookup
        enum JSON {
           case intValue(Int)
           case stringValue(String)
           case arrayValue(Array<JSON>)
           case dictionaryValue(Dictionary<String, JSON>)
        
           var stringValue: String? {
              if case .stringValue(let str) = self {
                 return str
              }
              return nil
           }
        
           subscript(index: Int) -> JSON? {
              if case .arrayValue(let arr) = self {
                 return index < arr.count ? arr[index] : nil
              }
              return nil
           }
        
           subscript(key: String) -> JSON? {
              if case .dictionaryValue(let dict) = self {
                 return dict[key]
              }
              return nil
           }
        
           subscript(dynamicMember member: String) -> JSON? {
              if case .dictionaryValue(let dict) = self {
                 return dict[member]
              }
              return nil
           }
        }
    

    如果没有@dynamicMemberLookup关键字。我们操作一个JSON实例就会像下面这样:

    json[0]?["name"]?["first"]?.stringValue
    

    当使用@dynamicMemberLookup关键字后

    json[0]?.name?.first?.stringValue
    

    这样的语法糖可以让你的代码语义话更强。阅读起来更方便。

    你可能会想为什么会有 @dynamicMemberLookUp 这种迷幻的存在,在第一个Demo中直接定义一个属性name不就好了么。
    其实@dynamicMemberLookUp的设计不单单是为了纯Swift的工程而考虑,像在机器学习,或者与其他语言之间相互桥接会有很大的用处。 这对于Swift语言来说还是很有帮助的。

    参考资料:
    https://www.hackingwithswift.com/articles/55/how-to-use-dynamic-member-lookup-in-swift

    https://www.swiftbysundell.com/tips/combining-dynamic-member-lookup-with-key-paths

    相关文章

      网友评论

        本文标题:Swift 中的 @dynamicMemberLookup注解

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