<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Generic on Chen</title><link>https://hechen.github.io/zh-cn/tags/generic/</link><description>Recent content in Generic on Chen</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sun, 29 Sep 2019 10:30:30 +0800</lastBuildDate><atom:link href="https://hechen.github.io/zh-cn/tags/generic/index.xml" rel="self" type="application/rss+xml"/><item><title>Alamofire 和 RxSwift 中的 .af 以及 .rx 扩展是怎么实现的</title><link>https://hechen.github.io/zh-cn/post/alamofire-rxswift-af-rx/</link><pubDate>Sun, 29 Sep 2019 10:30:30 +0800</pubDate><guid>https://hechen.github.io/zh-cn/post/alamofire-rxswift-af-rx/</guid><description>&lt;p&gt;今天继续来一篇水文，关于 Alamofire 和 RxSwift 两个组件中扩展后缀 .af 以及 .rx 是怎么实现的。相信用过的 (￣ω￣(￣ω￣〃 (￣ω￣〃)ゝ 都看过了。我这里权当自己的记录流水账了。&lt;/p&gt;
&lt;p&gt;先来看 Alamofire 中关于 af 扩展的实现：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Alamofire" loading="lazy" src="https://i.imgur.com/AbPIzgX.png"&gt;&lt;/p&gt;
&lt;p&gt;使用 Alamofire 扩展的方式如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Demo&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="nc"&gt;Demo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AlamofireExtended&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="nc"&gt;AlamofireExtension&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;ExtendedType&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Demo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;printSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Something arrived.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Demo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;af&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里主要有两点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;为将要使用的类 Demo 扩展 &lt;code&gt;AlamofireExtended&lt;/code&gt; 协议，也就是增加 af 扩展属性，其返回的是一个封装对象 &lt;code&gt;AlamofireExtension&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;为 &lt;code&gt;AlamofireExtension&lt;/code&gt; 对象（1 中返回的封装类型）扩展专属于 Demo 这个类型的方法；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;说实话，这里用来封装元类型信息的结构体名称和扩展协议名称一样，我初次看的时候确实是蒙的。相对于 Alamofire 的命名来说，个人更喜欢 RxSwift 的命名。&lt;/p&gt;
&lt;p&gt;接下来是 RxSwift 中 Rx 扩展的实现：&lt;/p&gt;
&lt;p&gt;&lt;img alt="RxSwift" loading="lazy" src="https://i.imgur.com/m5O7lo5.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到，整个使用方式上是完全相同的。仅仅是各项名字不同。&lt;/p&gt;
&lt;p&gt;所以我们可以总结这种方式的使用路径，如何为我们自己开发的组件扩充命名空间，具体有三个地方：&lt;/p&gt;
&lt;h3 id="声明扩展属性"&gt;声明扩展属性&lt;/h3&gt;
&lt;p&gt;为了能够支持实例变量和类型两者，需要分别增加两个计算属性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个是 static 的，提供给类型使用；&lt;/li&gt;
&lt;li&gt;一个是实例变量，提供给单个实例来用；&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="封装元类型信息"&gt;封装元类型信息&lt;/h3&gt;
&lt;p&gt;为了能够使得 &lt;code&gt;.af/.rx&lt;/code&gt; 这些扩展属性也能够获得当前实例或者类型的元信息，不约而同的使用了结构体封装的形式，通过泛型类型实现。我们知道这个封装对象内部就是记录的就是 self&lt;/p&gt;</description></item></channel></rss>