@dynamicMemberLookup

168 阅读1分钟

动态成员查找

声明了@dynamicMemberLookup, 会动态的去查找属性成员, 调用下面的方法。不声明的时候, 作为安全类型语言, 是无法编译的。

需要实现的方法

subscript (dynamicMember member: String) -> Any

案例1

@dynamicMemberLookup

struct Test1 {

    subscript (dynamicMember member: String) -> String {
        return "Jack"
    }

    subscript (dynamicMember member: String) -> Int {
        return 18
    }
}

let t1 = Test1()
let name: String = t1.name
let age: Int = t1.age
print(name, age)

案例2 方法可以被重载

@dynamicMemberLookup

struct Person {
    subscript (dynamicMember member: String) -> String {
        let properties = ["name": "Jack", "preference": "football"]
        return properties[member, default: ""]
    }

    subscript (dynamicMember member: String) -> Int {
        return 18
    }
}

let p = Person()
// 必须要声明类型, 否则调用那个方法是模糊的
let test: String = p.test
let name: String = p.name
let preference: String = p.preference
let age: Int = p.age

@dynamicMemberLookup有啥用

@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
  }
}

取json 里面的值, 需要这样写

let json = JSON.stringValue("Example")
let s = json[0]?["name"]?["first"]?.stringValue

声明dynamicLookUp 时就可以这样使用

let s = json[0]?.name?.first?.stringValue

其实相当于执行了 json[0].name == json[0].subscript(dynamicMember member: "name")

通过这个方法拿到 json[0]字典key为name对应的值

subscript(dynamicMember member: String) -> JSON? {
      if case .dictionaryValue(let dict) = self {
         return dict[member]
      }
      return nil
   }

参考