动态成员查找是 Swift 中的一项功能特性,可提高与 Python 或 Javascript 等动态语言的互操作性。它允许动态成员查找调用看起来像访问类型属性的常规调用:

let people = People()
let name = people.name // 像访问属性一样

name是从字典中查找的,而不是作为 People 的属性访问的。

如何使用动态成员查找?

要在你的自定义类型中使用动态成员查找,请使用 @dynamicMemberLookup标注你的类型,并实现如下方法:

subscript(dynamicMember:)

该方法接收一个String或KeyPath类型参数

我们来看看People是如何实现动态成员查找的,下面是一个demo:

@dynamicMemberLookup
struct People {
private var map = ["name": "drbox", "job": "developer"]
subscript(dynamicMember key: String) -> String {
map[key] ?? "undefine"
}
}

现在你可以像访问它的属性一样查找 People 对象的成员。

let people = People()
let name = people.name
let job = people.job

我们分析一下People是如何实现动态成员查找的

  • 首先我们使用@dynamicMemberLookup标注了People类型
  • 实现了subscript(dynamicMember:)方法,该方法我们接收一个String类型的参数,并返回一个String类型值

现在你已经了解了动态成员查找的作用以及如何实现它。让我们通过KeyPath来看看另一个有用的例子。

struct Info {
let job: String
let homeAddr: String
} struct People {
let name: String
let info: Info
} let info = Info(job: "developer", homeAddr: "beijing")
let people = People(name: "drbox", info: info)
print("job: \(people.info.job)") // 访问成员属性的属性

通过调用people.info.job可以访问Info的属性值。但是,如果你想直接通过people.job 而不是people.info.job 调用它怎么办?

这时动态成员查找的KeyPath就派上用场了。

@dynamicMemberLookup
struct People {
let name: String
let info: Info subscript<T>(dynamicMember path: KeyPath<Info, T>) -> T {
info[keyPath: path]
}
} let info = Info(job: "developer", homeAddr: "beijing")
let people = People(name: "drbox", info: info)
print("job: \(people.job)") // 直接访问成员属性的属性

以上就是我们演示如何实现动态成员查找的例子,它让people.job成为了可能。这只是一个用于讲解动态成员查找的简单案例,但在实际开发中,我们最好不要这么做。

而动态成员查找在实际项目中的运用,你可以参考RxCocoa中Reactive,它运用动态成员查找,巧妙的为任何一个AnyObject类型的对象,增加了属性的Binder观察者。

@dynamicMemberLookup
public struct Reactive<Base> {
/// Base object to extend.
public let base: Base /// Creates extensions with base object.
///
/// - parameter base: Base object.
public init(_ base: Base) {
self.base = base
} /// Automatically synthesized binder for a key path between the reactive
/// base and one of its properties
public subscript<Property>(dynamicMember keyPath: ReferenceWritableKeyPath<Base, Property>) -> Binder<Property> where Base: AnyObject {
Binder(self.base) { base, value in
base[keyPath: keyPath] = value
}
}
}

例如:绑定UIView的背景色

@dynamicMemberLookup(动态成员查找)的更多相关文章

  1. Linux下动态库查找路径的问题

    说到和动态库查找路径相关的问题,总体上可以分为两类:    第一类: 通过源代码编译程序时出现的找不到某个依赖包的问题,而如果此时你恰好已经按照它的要求确确实实.千真万确.天地良心地把依赖库给装好了, ...

  2. 谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH PKG_CONFIG_PATH

    谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH  PKG_CONFIG_PATH 转载自:http://blog.chinaunix.net/xmlrpc.ph ...

  3. 谈谈Linux下动态库查找路径的问题

    学习到了一个阶段之后,就需要不断的总结.沉淀.清零,然后才能继续"上路".回想起自己当年刚接触Linux时,不管是用源码包编译程序,还是程序运行时出现的和动态库的各种恩恩怨怨,心里 ...

  4. [转]谈谈Linux下动态库查找路径的问题

    http://blog.chinaunix.net/uid-23069658-id-4028681.html 学习到了一个阶段之后,就需要不断的总结.沉淀.清零,然后才能继续“上路”.回想起自己当年刚 ...

  5. 转:谈谈Linux下动态库查找路径的问题

    http://blog.chinaunix.net/uid-23069658-id-4028681.html 学习到了一个阶段之后,就需要不断的总结.沉淀.清零,然后才能继续“上路”.回想起自己当年刚 ...

  6. jpa动态分页查找

    https://my.oschina.net/buwei/blog/172402 http://www.cnblogs.com/derry9005/p/6282571.html http://2560 ...

  7. 【.NET深呼吸】动态类型(扩充篇)

    前面两文中,老周已向大家介绍了关于动态类型对象的两种级别的使用方案,本篇呢,老周再讲一个自定义动态类型的例子. 前面给大家演示的例子中,动态类型中包装的是字典类型来存储数据的,这一次咱们换一种风味,老 ...

  8. Thinkphp查询 1.查询方式 2.表达式查询 3.快捷查询 4.区间查询 5.组合查询 6.统计查询 7.动态查询 8.SQL 查询

    1.使用字符串作为条件查询 $user = M('User'); var_dump($user->where('id=1 AND user="蜡笔小新"')->sele ...

  9. C# 动态语言扩展(11)

    在 C# 4 开始添加 dynamic 类型.Mono C# 已经支持 C# 6.0 了. DLR C# 4 动态功能是 Dynamic Language Runtime (动态语言运行时,DLR)的 ...

  10. 类的static成员并用其实现一个单例模式

    对于特定类型的全体对象而言,有时候可能需要访问一个全局的变量.比如说统计某种类型对象已创建的数量.如果我们用全局变量会破坏数据的封装,一般的用户代码都可以修改这个全局变量,这时我们可以用类的静态成员来 ...

随机推荐

  1. Spring6 DI 依赖注入--Bean属性赋值

    Spring6基于XML实现Bean 管理(属性赋值) IOC和DI有什么区别:DI是IOC中的具体实现,DI表示依赖注入或注入属性,注入属性要在创建对象的基础之上完成 依赖注入方法 bean属性赋值 ...

  2. 线程基础知识10-volatile

    1 简介 Volatile保证了可见性和有序性,没有保证原子性. 1.1 保证可见性简介 可见性就是指当一个线程修改了共享变量的值时,其他线程能够立即得知这个修改.volatile变量做到了这一点. ...

  3. Rpc-实现Zookeeper注册中心

    1.前言 本文章是笔主在声哥的手写RPC框架的学习下,对注册中心的一个拓展.因为声哥某些部分没有保留拓展性,所以本文章的项目与声哥的工程有部分区别,核心内容在Curator的注册发现与注销,思想看准即 ...

  4. 罗姆BU32107EFV缩写词

    ADC Analog-to-Digital Converter Att Attenuation 衰减 AMix Analog Mixing AVol Analog Volume BPF Band-Pa ...

  5. 关于Powerlink和EtherCAT的对比

    https://www.amobbs.com/thread-5679636-1-2.html 转发自:http://book.2cto.com/201508/55093.html 这个问题经常会被人问 ...

  6. 【python自动化测试】1- python基础和pycharm使用

    python基础和pycharm使用 1.pycharm 1.1 为特定格式文件添加头信息 File--Settings--Editor--File and Code Templates--Pytho ...

  7. JZOJ 4320. 【NOIP2015模拟11.5】旅行

    题目 思路 不想写了,直接使用 没错,关键就在求第 \(k\) 小的路径 上述提到堆的做法,我们可以用 \(STL\) 的优先队列来实现 只不过常数有点大~~~ \(Code\) #include&l ...

  8. 理论+实战,详解Sharding Sphere-jdbc

    摘要:Apache ShardingSphere 是一款分布式的数据库生态系统,它包含两大产品:ShardingSphere-Proxy和ShardingSphere-JDBC. 本文分享自华为云社区 ...

  9. MySQL 8.0 新特性-原子DDL

    背景 MySQL 8.0 原子DDL 是一个复杂的过程,涉及比较多的模块,例如:MDL 锁,表定义缓存,行格式,Row Log,DDL Log,online 属性,表空间物理文件操作等.本文主要通过与 ...

  10. MessageUtil

    1 public abstract class MessageUtil { 2 3 public static String changeMsg(CustomerReportQueryObject q ...