-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
236 lines (141 loc) · 102 KB
/
atom.xml
File metadata and controls
236 lines (141 loc) · 102 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>AidaHe‘s blog</title>
<link href="/atom.xml" rel="self"/>
<link href="http://yoursite.com/"/>
<updated>2020-06-07T08:43:24.928Z</updated>
<id>http://yoursite.com/</id>
<author>
<name>AidaHe</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>iOS 音频转码mp3,wav,amr格式</title>
<link href="http://yoursite.com/2020/06/07/2020/06/AudioConvert/"/>
<id>http://yoursite.com/2020/06/07/2020/06/AudioConvert/</id>
<published>2020-06-07T08:41:00.000Z</published>
<updated>2020-06-07T08:43:24.928Z</updated>
<content type="html"><![CDATA[<h2 id="主体功能:-Swift版本"><a href="#主体功能:-Swift版本" class="headerlink" title="主体功能:(Swift版本)"></a>主体功能:(Swift版本)</h2><h3 id="1、将录制的caf格式音频转码mp3格式"><a href="#1、将录制的caf格式音频转码mp3格式" class="headerlink" title="1、将录制的caf格式音频转码mp3格式"></a>1、将录制的caf格式音频转码mp3格式</h3><h3 id="2、wav格式与amr格式音频相互转码"><a href="#2、wav格式与amr格式音频相互转码" class="headerlink" title="2、wav格式与amr格式音频相互转码"></a>2、wav格式与amr格式音频相互转码</h3><a id="more"></a><p><img src="https://upload-images.jianshu.io/upload_images/6695792-89df03aedb60a15a.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="Mp3转码"><br><img src="https://upload-images.jianshu.io/upload_images/6695792-0486228cd085084a.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="Amr与Wav互转"></p><h4 id="申明:"><a href="#申明:" class="headerlink" title="申明:"></a>申明:</h4><p>核心转码功能非原创,摘录于各大博客平台。如有侵权,请联系删除。</p><h4 id="简介:"><a href="#简介:" class="headerlink" title="简介:"></a>简介:</h4><p>1、转mp3主要依赖于lame</p><p>2、wav与amr的转码应该注意录音(AVAudioRecorder)的参数设置,否则可能导致转码不成功eg:</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">let</span> recordSetting: [<span class="type">String</span>:<span class="type">Any</span>] = [</span><br><span class="line"></span><br><span class="line"> <span class="type">AVSampleRateKey</span>:<span class="type">NSNumber</span>(value:<span class="number">16000</span>),<span class="comment">//采样率</span></span><br><span class="line"></span><br><span class="line"> <span class="type">AVEncoderBitRateKey</span>:<span class="type">NSNumber</span>(value: <span class="number">16000</span>),</span><br><span class="line"></span><br><span class="line"> <span class="type">AVFormatIDKey</span>: <span class="type">NSNumber</span>(value: kAudioFormatLinearPCM),<span class="comment">//音频格式</span></span><br><span class="line"></span><br><span class="line"> <span class="type">AVNumberOfChannelsKey</span>: <span class="type">NSNumber</span>(value: <span class="number">1</span>),<span class="comment">//通道数</span></span><br><span class="line"></span><br><span class="line"> <span class="type">AVLinearPCMBitDepthKey</span>:<span class="type">NSNumber</span>(value: <span class="number">16</span>),</span><br><span class="line"></span><br><span class="line"> <span class="type">AVEncoderAudioQualityKey</span>: <span class="type">NSNumber</span>(value: <span class="type">AVAudioQuality</span>.<span class="built_in">max</span>.rawValue)<span class="comment">//录音质量</span></span><br><span class="line"></span><br><span class="line"> ];</span><br></pre></td></tr></table></figure><p>项目地址 <a href="https://github.com/SingletonH/SwiftRecorder" target="_blank" rel="noopener">https://github.com/SingletonH/SwiftRecorder</a></p>]]></content>
<summary type="html">
<h2 id="主体功能:-Swift版本"><a href="#主体功能:-Swift版本" class="headerlink" title="主体功能:(Swift版本)"></a>主体功能:(Swift版本)</h2><h3 id="1、将录制的caf格式音频转码mp3格式"><a href="#1、将录制的caf格式音频转码mp3格式" class="headerlink" title="1、将录制的caf格式音频转码mp3格式"></a>1、将录制的caf格式音频转码mp3格式</h3><h3 id="2、wav格式与amr格式音频相互转码"><a href="#2、wav格式与amr格式音频相互转码" class="headerlink" title="2、wav格式与amr格式音频相互转码"></a>2、wav格式与amr格式音频相互转码</h3>
</summary>
<category term="iOS" scheme="http://yoursite.com/categories/iOS/"/>
<category term="iOS" scheme="http://yoursite.com/tags/iOS/"/>
<category term="Swift" scheme="http://yoursite.com/tags/Swift/"/>
<category term="音频" scheme="http://yoursite.com/tags/%E9%9F%B3%E9%A2%91/"/>
</entry>
<entry>
<title>Swift 定位权限封装,坐标转换</title>
<link href="http://yoursite.com/2020/05/30/2020/05/AHLocationManager/"/>
<id>http://yoursite.com/2020/05/30/2020/05/AHLocationManager/</id>
<published>2020-05-30T08:55:00.000Z</published>
<updated>2020-05-30T08:58:07.431Z</updated>
<content type="html"><![CDATA[<h4 id="功能列表"><a href="#功能列表" class="headerlink" title="功能列表"></a>功能列表</h4><ul><li>获取系统经纬度坐标</li><li>GPS国际标准,高德坐标,百度坐标相互转换</li><li>定位权限被拒弹框提示<h4 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h4><h5 id="1,将源文件AHLocationManager-swift引入项目中"><a href="#1,将源文件AHLocationManager-swift引入项目中" class="headerlink" title="1,将源文件AHLocationManager.swift引入项目中"></a>1,将源文件AHLocationManager.swift引入项目中</h5><blockquote><p><a href="https://github.com/AidaHe/AHLocationManager" target="_blank" rel="noopener">https://github.com/AidaHe/AHLocationManager</a></p></blockquote><h5 id="2,添加info-plist-描述"><a href="#2,添加info-plist-描述" class="headerlink" title="2,添加info.plist 描述"></a>2,添加info.plist 描述</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><key>NSLocationAlwaysAndWhenInUseUsageDescription</key></span><br><span class="line"><string>App需要您的同意,才能访问位置以便xxx</string></span><br><span class="line"><key>NSLocationWhenInUseUsageDescription</key></span><br><span class="line"><string>App需要您的同意,才能访问位置以便xxx</string></span><br></pre></td></tr></table></figure><a id="more"></a><h5 id="3,调用"><a href="#3,调用" class="headerlink" title="3,调用"></a>3,调用</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">AHLocationManager.shared.startPositioning(self)</span><br><span class="line">AHLocationManager.shared.locationType = .BD</span><br><span class="line">AHLocationManager.shared.postionUpdateClosure = {[weak self] (locModel) in</span><br><span class="line"> if locModel.locationError != nil {</span><br><span class="line"> self?.locationLabel.text = "定位失败"</span><br><span class="line"> }else{</span><br><span class="line"> if let coordinate = locModel.coordinate{</span><br><span class="line"> self?.latLabel.text = "\(coordinate.latitude)"</span><br><span class="line"> self?.longLabel.text = "\(coordinate.longitude)"</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> if let place = locModel.clplacemark {</span><br><span class="line"> self?.locationLabel.text = "\(place.administrativeArea ?? "")\(place.locality ?? "")\(place.subLocality ?? "")\(place.thoroughfare ?? "")\(place.name ?? "")"</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">enum AHLocationType{</span><br><span class="line"> /// WGS-84:是国际标准,GPS坐标(Google Earth使用、或者GPS模块)</span><br><span class="line"> case WGS</span><br><span class="line"> /// GCJ-02:中国坐标偏移标准,Google Map、高德、腾讯使用</span><br><span class="line"> case GCJ</span><br><span class="line"> /// BD-09 :百度坐标偏移标准,Baidu Map使用</span><br><span class="line"> case BD</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure>通过<code>locationType</code>可指定返回经纬度类型,默认返回的经纬度为<code>WGS-84</code><blockquote><p>坐标转换参考<a href="https://www.jianshu.com/p/abdb35b0ba78" target="_blank" rel="noopener">https://www.jianshu.com/p/abdb35b0ba78</a><br>坐标转换可能存在一定误差,使用时自行斟酌</p></blockquote></li></ul>]]></content>
<summary type="html">
<h4 id="功能列表"><a href="#功能列表" class="headerlink" title="功能列表"></a>功能列表</h4><ul>
<li>获取系统经纬度坐标</li>
<li>GPS国际标准,高德坐标,百度坐标相互转换</li>
<li>定位权限被拒弹框提示<h4 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h4><h5 id="1,将源文件AHLocationManager-swift引入项目中"><a href="#1,将源文件AHLocationManager-swift引入项目中" class="headerlink" title="1,将源文件AHLocationManager.swift引入项目中"></a>1,将源文件AHLocationManager.swift引入项目中</h5><blockquote>
<p><a href="https://github.com/AidaHe/AHLocationManager" target="_blank" rel="noopener">https://github.com/AidaHe/AHLocationManager</a></p>
</blockquote>
<h5 id="2,添加info-plist-描述"><a href="#2,添加info-plist-描述" class="headerlink" title="2,添加info.plist 描述"></a>2,添加info.plist 描述</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;key&gt;NSLocationAlwaysAndWhenInUseUsageDescription&lt;&#x2F;key&gt;</span><br><span class="line">&lt;string&gt;App需要您的同意,才能访问位置以便xxx&lt;&#x2F;string&gt;</span><br><span class="line">&lt;key&gt;NSLocationWhenInUseUsageDescription&lt;&#x2F;key&gt;</span><br><span class="line">&lt;string&gt;App需要您的同意,才能访问位置以便xxx&lt;&#x2F;string&gt;</span><br></pre></td></tr></table></figure>
</summary>
<category term="iOS" scheme="http://yoursite.com/categories/iOS/"/>
<category term="iOS" scheme="http://yoursite.com/tags/iOS/"/>
<category term="Swift" scheme="http://yoursite.com/tags/Swift/"/>
<category term="定位" scheme="http://yoursite.com/tags/%E5%AE%9A%E4%BD%8D/"/>
</entry>
<entry>
<title>iOS 跳转高德,百度,腾讯,谷歌,苹果地图导航</title>
<link href="http://yoursite.com/2020/05/24/2020/05/Navigation/"/>
<id>http://yoursite.com/2020/05/24/2020/05/Navigation/</id>
<published>2020-05-24T04:38:00.000Z</published>
<updated>2020-05-24T04:45:44.314Z</updated>
<content type="html"><![CDATA[<h4 id="一、info-plist文件添加Schemes"><a href="#一、info-plist文件添加Schemes" class="headerlink" title="一、info.plist文件添加Schemes"></a>一、info.plist文件添加Schemes</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><key>LSApplicationQueriesSchemes</key></span><br><span class="line"> <array></span><br><span class="line"> <string>iosamap</string></span><br><span class="line"> <string>baidumap</string></span><br><span class="line"> <string>comgooglemaps</string></span><br><span class="line"> <string>qqmap</string></span><br><span class="line"> </array></span><br></pre></td></tr></table></figure><h4 id="二、获取当前经纬度和地址"><a href="#二、获取当前经纬度和地址" class="headerlink" title="二、获取当前经纬度和地址"></a>二、获取当前经纬度和地址</h4><a id="more"></a><h4 id="三、开始导航"><a href="#三、开始导航" class="headerlink" title="三、开始导航"></a>三、开始导航</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line">UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"请选择导航" message:nil preferredStyle:UIAlertControllerStyleActionSheet];</span><br><span class="line"> UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];</span><br><span class="line"> </span><br><span class="line"> NSURL * apple_App = [NSURL URLWithString:@"http://maps.apple.com/"];</span><br><span class="line"> float latitude = [_model.latitude floatValue];</span><br><span class="line"> float longitude = [_model.longitude floatValue];</span><br><span class="line"> float locLaitude = self.localLatitude;</span><br><span class="line"> float locLongitude = self.localLongitude;</span><br><span class="line"> NSString *locAddress = self.localAddress;</span><br><span class="line"> NSString *address = _model.address;</span><br><span class="line"> UIAlertAction *appleAction = [UIAlertAction actionWithTitle:@"苹果地图" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {</span><br><span class="line"> if ([[UIApplication sharedApplication] canOpenURL:apple_App]) {</span><br><span class="line"> NSString *urlString=[NSString stringWithFormat:@"http://maps.apple.com/?saddr=%f,%f&daddr=%f,%f",locLaitude ,locLongitude,latitude,longitude ];</span><br><span class="line"> [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];</span><br><span class="line"> }else{</span><br><span class="line"> [SVProgressHUD showSuccessWithStatus:@"请先安装苹果地图客户端"];</span><br><span class="line"> }</span><br><span class="line"> }];</span><br><span class="line"> </span><br><span class="line"> NSURL * gaode_App = [NSURL URLWithString:@"iosamap://"];</span><br><span class="line"> UIAlertAction *gaodeAction = [UIAlertAction actionWithTitle:@"高德地图" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {</span><br><span class="line"> if ([[UIApplication sharedApplication] canOpenURL:gaode_App]) {</span><br><span class="line"> NSString *urlString=[[NSString stringWithFormat:@"iosamap://path?sourceApplication=%@&sid=BGVIS1&slat=%f&slon=%f&sname=%@&did=BGVIS2&dlat=%f&dlon=%f&dname=%@&dev=0&t=0",locAddress,locLaitude,locLongitude,locAddress,latitude,longitude,address] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];</span><br><span class="line"> [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];</span><br><span class="line"> }else{</span><br><span class="line"> [SVProgressHUD showSuccessWithStatus:@"请先安装高德地图客户端"];</span><br><span class="line"> }</span><br><span class="line"> }];</span><br><span class="line"> </span><br><span class="line"> NSURL * baidu_App = [NSURL URLWithString:@"baidumap://"];</span><br><span class="line"> UIAlertAction *baiduAction = [UIAlertAction actionWithTitle:@"百度地图" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {</span><br><span class="line"> if ([[UIApplication sharedApplication] canOpenURL:baidu_App]) {</span><br><span class="line"> NSString *urlString=[[NSString stringWithFormat:@"baidumap://map/direction?origin={{我的位置}}&destination=latlng:%f,%f|name=目的地&mode=driving&coord_type=gcj02",latitude,longitude] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];</span><br><span class="line"> [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];</span><br><span class="line"> }else{</span><br><span class="line"> [SVProgressHUD showSuccessWithStatus:@"请先安装百度地图客户端"];</span><br><span class="line"> }</span><br><span class="line"> }];</span><br><span class="line"> </span><br><span class="line"> NSURL * tencent_App = [NSURL URLWithString:@"qqmap://"];</span><br><span class="line"> UIAlertAction *tencentAction = [UIAlertAction actionWithTitle:@"腾讯地图" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {</span><br><span class="line"> if ([[UIApplication sharedApplication] canOpenURL:tencent_App]) {</span><br><span class="line"> NSString *urlString=[[NSString stringWithFormat:@"qqmap://map/routeplan?type=drive&fromcoord=%f,%f&tocoord=%f,%f&policy=1",locLaitude,locLongitude,latitude,longitude] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];</span><br><span class="line"> [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];</span><br><span class="line"> }else{</span><br><span class="line"> [SVProgressHUD showSuccessWithStatus:@"请先安装腾讯地图客户端"];</span><br><span class="line"> }</span><br><span class="line"> }];</span><br><span class="line"> </span><br><span class="line"> NSURL * google_App = [NSURL URLWithString:@"comgooglemaps://"];</span><br><span class="line"> UIAlertAction *googleAction = [UIAlertAction actionWithTitle:@"谷歌地图" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {</span><br><span class="line"> if ([[UIApplication sharedApplication] canOpenURL:google_App]) {</span><br><span class="line"> NSString *urlString=[[NSString stringWithFormat:@"comgooglemaps://?x-source=%@&x-success=%@&saddr=&daddr=%f,%f&directionsmode=driving",@"***",@"ChuanLaoDa",latitude,locLongitude] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];</span><br><span class="line"> [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];</span><br><span class="line"> </span><br><span class="line"> }else{</span><br><span class="line"> [SVProgressHUD showSuccessWithStatus:@"请先安装谷歌地图客户端"];</span><br><span class="line"> }</span><br><span class="line"> }];</span><br><span class="line"> </span><br><span class="line"> [alertVC addAction:cancelAction];</span><br><span class="line"> [alertVC addAction:appleAction];</span><br><span class="line"> [alertVC addAction:gaodeAction];</span><br><span class="line"> [alertVC addAction:baiduAction];</span><br><span class="line"> [alertVC addAction:tencentAction];</span><br><span class="line"> [alertVC addAction:googleAction];</span><br><span class="line"> [self presentViewController:alertVC animated:false completion:nil];</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h4 id="一、info-plist文件添加Schemes"><a href="#一、info-plist文件添加Schemes" class="headerlink" title="一、info.plist文件添加Schemes"></a>一、info.plist文件添加Schemes</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;key&gt;LSApplicationQueriesSchemes&lt;&#x2F;key&gt;</span><br><span class="line"> &lt;array&gt;</span><br><span class="line"> &lt;string&gt;iosamap&lt;&#x2F;string&gt;</span><br><span class="line"> &lt;string&gt;baidumap&lt;&#x2F;string&gt;</span><br><span class="line"> &lt;string&gt;comgooglemaps&lt;&#x2F;string&gt;</span><br><span class="line"> &lt;string&gt;qqmap&lt;&#x2F;string&gt;</span><br><span class="line"> &lt;&#x2F;array&gt;</span><br></pre></td></tr></table></figure>
<h4 id="二、获取当前经纬度和地址"><a href="#二、获取当前经纬度和地址" class="headerlink" title="二、获取当前经纬度和地址"></a>二、获取当前经纬度和地址</h4>
</summary>
<category term="iOS" scheme="http://yoursite.com/categories/iOS/"/>
<category term="iOS" scheme="http://yoursite.com/tags/iOS/"/>
<category term="OC" scheme="http://yoursite.com/tags/OC/"/>
<category term="Map" scheme="http://yoursite.com/tags/Map/"/>
</entry>
<entry>
<title>仿App Store转场动画 Swift语言实现</title>
<link href="http://yoursite.com/2020/05/17/2020/05/AppStoreTransition/"/>
<id>http://yoursite.com/2020/05/17/2020/05/AppStoreTransition/</id>
<published>2020-05-17T02:38:00.000Z</published>
<updated>2020-05-18T13:39:46.973Z</updated>
<content type="html"><![CDATA[<h3 id="参考文档:"><a href="#参考文档:" class="headerlink" title="参考文档:"></a>参考文档:</h3><blockquote><p><a href="https://www.jianshu.com/p/d802eb2e5a31" target="_blank" rel="noopener">https://www.jianshu.com/p/d802eb2e5a31</a><br>本文主体思路是参考该博主的OC版本实现的<br><a href="https://www.jianshu.com/p/8a99020d954f" target="_blank" rel="noopener">https://www.jianshu.com/p/8a99020d954f</a><br>此文章介绍了转场动画中相关的一些概念,我感觉还是挺通俗易懂的。</p></blockquote><h3 id="效果图:"><a href="#效果图:" class="headerlink" title="效果图:"></a>效果图:</h3><p><img src="https://upload-images.jianshu.io/upload_images/6695792-899f9bb7318751e1.gif?imageMogr2/auto-orient/strip" alt="效果图"></p><a id="more"></a><h3 id="场景分析:"><a href="#场景分析:" class="headerlink" title="场景分析:"></a>场景分析:</h3><p>1、某日,我看到App Store上首页花里胡哨的转场动画体验着实不错,便想着自己实现一番。<br>2、作为一个萌新看到这样的效果完全联想不到是用何等操作实现的,so,百度,于是找到一个OC版。<br>3、然后也知道此效果主要是通过重写系统的<code>push</code>、<code>pop</code>动画达到的。作为一个<code>Swift</code>偏好者,难免不想翻译一下。<br>4、既然是需要<code>push</code>、<code>pop</code>,那么第一步是需要<code>navigationController</code>,我是直接在<code>StoryBoard</code>中嵌入的。<br>5、接下来是首页<code>TableView</code>布局,<code>cell</code>触摸缩小放大。<br>6、点击<code>cell Push</code>到详情页,本文重点,先放到后面再详说。<br>7、详情页依旧是<code>TableView</code>布局。顶部大图为<code>Header</code>,底部为文本,动态计算高度即可。<br>8、详情页伴随着左滑手势将页面按一定比例缩小,当缩小一定程度时<code>Pop</code>回首页。<br>9、不难发现,在详情页左滑时还有一个模糊的背景正是首页的截图。</p><h3 id="代码实现:"><a href="#代码实现:" class="headerlink" title="代码实现:"></a>代码实现:</h3><p>除了不知道如何重写<code>pop</code>和<code>push</code>之外其余思路清晰之后,便可以开始绘制基本UI了<br><img src="https://upload-images.jianshu.io/upload_images/6695792-f666c487494066c5.gif?imageMogr2/auto-orient/strip" alt="系统push、pop效果"></p><h4 id="一、重写Push、实现Delegate"><a href="#一、重写Push、实现Delegate" class="headerlink" title="一、重写Push、实现Delegate"></a>一、重写Push、实现Delegate</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">extension ViewController:UINavigationControllerDelegate,UIViewControllerAnimatedTransitioning{</span><br><span class="line"> func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {</span><br><span class="line"> return 1.0</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?{</span><br><span class="line"> return self</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>此时我们再来仔细观察从首页点击<code>cell</code>之后<code>push</code>到详情页这之间发生了什么?不难发现,其实就是将<code>cell</code>放大,有一种弹出的效果,而系统的<code>push</code>默认效果是新页面从左边覆盖过来。</p><blockquote><p>其实呢,在转场的过程中系统会提供一个视图容器用来盛装进行跳转控制器的视图,如下图所示,当前的<code>FirstViewController</code> <code>present</code>到<code>SecondViewController</code>的时候,此时,<code>FirstViewController</code>的<code>view</code>变成<code>fromView</code>,这个视图会自动加入到<code>transtition container view</code>中,然后在跳转过程中我们需要做的就是将<code>SecondViewController</code>的视图(此时是toView)加入到这个容器中,然后为这个toView的展现增加动画。<br>以上内容摘录自此处<br>作者:劉光軍_Shine<br>链接:<a href="https://www.jianshu.com/p/8a99020d954f" target="_blank" rel="noopener">https://www.jianshu.com/p/8a99020d954f</a><br>來源:简书</p></blockquote><p>有了一定概念之后,我们来解读一下下面的逻辑<br>1、拿到<code>toView</code>:即将要展示的视图,<code>fromView</code>:当前页面已展示的<code>view</code><br>2、拿到<code>toView,fromView</code>之后,即将要展示动画,先将<code>fromView</code>隐藏,操作<code>toView</code>的<code>frame</code>和<code>alpha</code>以达到弹出放大的效果<br>3、将需要展示动画的<code>view</code>设置相应位置之后添加到<code>transitionContext</code>中<br>4、展示动画<code>toView.alpha 0~>1</code> 逐渐显示,<code>frame</code> 首页<code>cell frame~></code> 详情页<code>header frame</code> 逐渐放大<br>5、移除用于展示动画的<code>view</code>,显示详情页<code>view</code>,显示首页<code>view</code></p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">animateTransition</span><span class="params">(using transitionContext: UIViewControllerContextTransitioning)</span></span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> cell:<span class="type">HomeTableViewCell</span> = tableView.cellForRow(at: selectIndexPath!) <span class="keyword">as</span>! <span class="type">HomeTableViewCell</span></span><br><span class="line"> <span class="keyword">let</span> toVC:<span class="type">UIViewController</span> = transitionContext.viewController(forKey: .to)!</span><br><span class="line"> <span class="keyword">let</span> toView:<span class="type">UIImageView</span> = toVC.value(forKeyPath:<span class="string">"headerImageView"</span>) <span class="keyword">as</span>! <span class="type">UIImageView</span></span><br><span class="line"> <span class="keyword">let</span> fromView = cell.bgView</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> containerView = transitionContext.containerView</span><br><span class="line"> <span class="keyword">let</span> snapshotView = <span class="type">UIImageView</span>(image: cell.bgImageView!.image)</span><br><span class="line"> snapshotView.frame = containerView.convert((fromView?.frame)!, from: fromView?.superview)</span><br><span class="line"></span><br><span class="line"> fromView?.isHidden = <span class="literal">true</span></span><br><span class="line"> toVC.view.frame = transitionContext.finalFrame(<span class="keyword">for</span>: toVC)</span><br><span class="line"> toVC.view.alpha = <span class="number">0</span></span><br><span class="line"> toView.isHidden = <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> titleLabel = <span class="type">UILabel</span>(frame: <span class="type">CGRect</span>(x: <span class="number">15</span>, y: <span class="number">20</span>, width: kScreenWidth-<span class="number">30</span>, height: <span class="number">30</span>))</span><br><span class="line"> titleLabel.textColor = <span class="type">UIColor</span>.white</span><br><span class="line"> titleLabel.font = <span class="type">UIFont</span>.boldSystemFont(ofSize: <span class="number">25</span>)</span><br><span class="line"> titleLabel.text = cell.titleLabel?.text</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> contentLabel = <span class="type">UILabel</span>(frame: <span class="type">CGRect</span>(x: <span class="number">15</span>, y: (kScreenWidth-<span class="number">40</span>)*<span class="number">1.3</span>-<span class="number">30</span>, width: kScreenWidth-<span class="number">30</span>, height: <span class="number">15</span>))</span><br><span class="line"> contentLabel.textColor = <span class="type">UIColor</span>.white</span><br><span class="line"> contentLabel.text = cell.contentLabel?.text</span><br><span class="line"> contentLabel.font = <span class="type">UIFont</span>(name: <span class="string">"PingFangSC-Light"</span>, size: <span class="number">15</span>)</span><br><span class="line"> contentLabel.alpha = <span class="number">0.5</span></span><br><span class="line"> snapshotView.addSubview(titleLabel)</span><br><span class="line"> snapshotView.addSubview(contentLabel)</span><br><span class="line"></span><br><span class="line"> containerView.addSubview(toVC.view)</span><br><span class="line"> containerView.addSubview(snapshotView)</span><br><span class="line"></span><br><span class="line"> <span class="type">UIView</span>.animate(withDuration: <span class="keyword">self</span>.transitionDuration(using: transitionContext), delay: <span class="number">0.0</span>, usingSpringWithDamping: <span class="number">0.6</span>, initialSpringVelocity: <span class="number">1.0</span>, options: .curveLinear, animations: {</span><br><span class="line"> containerView.layoutIfNeeded()</span><br><span class="line"> toVC.view.alpha = <span class="number">1.0</span></span><br><span class="line"> <span class="keyword">self</span>.view.frame = <span class="type">CGRect</span>(x: <span class="number">0</span>, y: <span class="number">0</span>, width: kScreenWidth, height: kScreenHeight)</span><br><span class="line"> snapshotView.frame = containerView.convert(toView.frame, from: toView.superview)</span><br><span class="line"> titleLabel.frame = <span class="type">CGRect</span>(x: <span class="number">22</span>, y: <span class="number">30</span>, width: kScreenWidth - <span class="number">30</span>, height: <span class="number">30</span>)</span><br><span class="line"> contentLabel.frame = <span class="type">CGRect</span>(x: <span class="number">22</span>, y: kScreenWidth*<span class="number">1.3</span>-<span class="number">30</span>, width: kScreenWidth*<span class="number">1.3</span>-<span class="number">44</span>, height: <span class="number">15</span>)</span><br><span class="line"></span><br><span class="line"> }) { (finished) <span class="keyword">in</span></span><br><span class="line"></span><br><span class="line"> toView.isHidden = <span class="literal">false</span></span><br><span class="line"> fromView?.isHidden = <span class="literal">false</span></span><br><span class="line"> snapshotView.removeFromSuperview()</span><br><span class="line"> <span class="keyword">self</span>.tableView.reloadData()</span><br><span class="line"> transitionContext.completeTransition(<span class="literal">true</span>)</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h4 id="二、将首页截图传递给详情页备用"><a href="#二、将首页截图传递给详情页备用" class="headerlink" title="二、将首页截图传递给详情页备用"></a>二、将首页截图传递给详情页备用</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">//MARK: 截屏</span><br><span class="line"> func imageFromView() ->UIImage{</span><br><span class="line"> UIGraphicsBeginImageContext(self.view.frame.size)</span><br><span class="line"> let context = UIGraphicsGetCurrentContext()</span><br><span class="line"> self.view.layer.render(in: context!)</span><br><span class="line"> let image = UIGraphicsGetImageFromCurrentImageContext()</span><br><span class="line"> UIGraphicsEndImageContext()</span><br><span class="line"> </span><br><span class="line"> return image!</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h4 id="三、详情页添加左滑返回手势"><a href="#三、详情页添加左滑返回手势" class="headerlink" title="三、详情页添加左滑返回手势"></a>三、详情页添加左滑返回手势</h4><p>1、给详情页的<code>tableView</code>添加手势<br>2、滑动过程中,实时获取当前滑动位置到初始位置的距离,实时计算该距离占据屏幕比例,相应缩小<code>tableView</code>大小并添加适应的圆角<br>3、手势结束时,获取手势发生的开始位置,手势结束后获取结束位置,计算出总共滑动范围<br>4、依据滑动范围所占屏幕的比例从而决定是否<code>pop</code>回上一页。若比例达到返回上一页,重写<code>pop</code>动画与<code>push</code>类似。若比例未达到,恢复详情页<code>tableView frame</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line">@objc func handleGesture(_ sender:UIGestureRecognizer){</span><br><span class="line"> </span><br><span class="line"> weak var weakSelf = self</span><br><span class="line"> </span><br><span class="line"> switch sender.state {</span><br><span class="line"> case .began:</span><br><span class="line"> print("手势开始---")</span><br><span class="line"> let currentPoint = sender.location(in: self.detailTableView)</span><br><span class="line"> startPointX = currentPoint.x</span><br><span class="line"> startPointY = currentPoint.y</span><br><span class="line"> isHorizontal = (startPointX > CGFloat(30)) ? false : true</span><br><span class="line"> break</span><br><span class="line"> case .changed:</span><br><span class="line"> print("拖动中----")</span><br><span class="line"> let currentPoint = sender.location(in: self.detailTableView)</span><br><span class="line"> </span><br><span class="line"> if isHorizontal {</span><br><span class="line"> if ((currentPoint.x-startPointX)>(currentPoint.y-startPointY)) {</span><br><span class="line"> scale = (kScreenWidth-(currentPoint.x-startPointX))/kScreenWidth</span><br><span class="line"> } else {</span><br><span class="line"> scale = (kScreenHeight-(currentPoint.y-startPointY))/kScreenHeight</span><br><span class="line"> }</span><br><span class="line"> } else {</span><br><span class="line"> scale = (kScreenHeight-(currentPoint.y-startPointY))/kScreenHeight</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> if (scale > CGFloat(1)) {</span><br><span class="line"> scale = CGFloat(1)</span><br><span class="line"> } else if (scale <= CGFloat(0.8)) {</span><br><span class="line"> scale = CGFloat(0.8);</span><br><span class="line"> }</span><br><span class="line"> if (self.detailTableView!.contentOffset.y<=0) {</span><br><span class="line"> // 缩放</span><br><span class="line"> self.detailTableView!.transform = CGAffineTransform(scaleX: scale, y: scale)</span><br><span class="line"> // 圆角</span><br><span class="line"> self.detailTableView!.layer.cornerRadius = 15 * (1-scale)*5*1.08;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> self.detailTableView!.isScrollEnabled = (scale < 0.99) ? false : true</span><br><span class="line"> break</span><br><span class="line"> case .ended:</span><br><span class="line"> print("手势结束--")</span><br><span class="line"> if(scale == 0.8){</span><br><span class="line"> DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {</span><br><span class="line"> weakSelf?.navigationController?.popViewController(animated: true)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> self.detailTableView!.isScrollEnabled = true</span><br><span class="line"> if scale > CGFloat(0.8) {</span><br><span class="line"> UIView.animate(withDuration: 0.2) {</span><br><span class="line"> weakSelf?.detailTableView!.layer.cornerRadius = 0</span><br><span class="line"> weakSelf?.detailTableView!.transform = CGAffineTransform(scaleX: 1, y: 1)</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"> break</span><br><span class="line"> default:</span><br><span class="line"> break</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>1、如果实际开发中多处需要用到这种转场效果可以抽出一个工具类来。<br>2、其实<code>App Store</code>中<code>pop</code>回来还有一个效果就是返回到首页时下面的文字说明会像一个抽屉一样由下往上收回的效果,有时间再去研究一下。另外,<code>App Store</code>上的背景配色之类一些细节处理也是非常极致的,有兴趣的朋友可以继续深究。<br>3、如有不足之处,望各路大神斧正。<br>4、<a href="https://github.com/SingletonH/SwiftTransition.git" target="_blank" rel="noopener">源码地址:https://github.com/SingletonH/SwiftTransition.git</a></p>]]></content>
<summary type="html">
<h3 id="参考文档:"><a href="#参考文档:" class="headerlink" title="参考文档:"></a>参考文档:</h3><blockquote>
<p><a href="https://www.jianshu.com/p/d802eb2e5a31" target="_blank" rel="noopener">https://www.jianshu.com/p/d802eb2e5a31</a><br>本文主体思路是参考该博主的OC版本实现的<br><a href="https://www.jianshu.com/p/8a99020d954f" target="_blank" rel="noopener">https://www.jianshu.com/p/8a99020d954f</a><br>此文章介绍了转场动画中相关的一些概念,我感觉还是挺通俗易懂的。</p>
</blockquote>
<h3 id="效果图:"><a href="#效果图:" class="headerlink" title="效果图:"></a>效果图:</h3><p><img src="https://upload-images.jianshu.io/upload_images/6695792-899f9bb7318751e1.gif?imageMogr2/auto-orient/strip" alt="效果图"></p>
</summary>
<category term="Swift" scheme="http://yoursite.com/categories/Swift/"/>
<category term="Swift" scheme="http://yoursite.com/tags/Swift/"/>
<category term="App Store" scheme="http://yoursite.com/tags/App-Store/"/>
<category term="Transition" scheme="http://yoursite.com/tags/Transition/"/>
</entry>
<entry>
<title>Swift中的Extension</title>
<link href="http://yoursite.com/2020/05/09/2020/05/SwiftExtension/"/>
<id>http://yoursite.com/2020/05/09/2020/05/SwiftExtension/</id>
<published>2020-05-09T11:31:00.000Z</published>
<updated>2020-05-09T11:39:39.547Z</updated>
<content type="html"><![CDATA[<p>Swift中可以对类,结构体,协议,枚举进行拓展添加新的功能<br>考虑到本篇博文中的篇幅,关于枚举的拓展将在下一篇介绍<code>ps:</code>基于Swift 5<br>Swift 中的扩展可以:</p><ul><li>一、添加计算型属性和计算型静态属性</li><li>二、定义实例方法和类型方法</li><li>三、提供新的构造器</li><li>四、定义下标</li><li>五、定义和使用新的嵌套类型</li><li>六、使一个已有类型符合某个协议<a id="more"></a><h4 id="一、添加计算型属性、计算型静态属性、“存储属性”"><a href="#一、添加计算型属性、计算型静态属性、“存储属性”" class="headerlink" title="一、添加计算型属性、计算型静态属性、“存储属性”"></a>一、添加计算型属性、计算型静态属性、“存储属性”</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">class Animal:NSObject {</span><br><span class="line"> var age:Int?</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">private var animalName:String = ""</span><br><span class="line">extension Animal {</span><br><span class="line"> //1添加静态计算属性</span><br><span class="line"> static var c:Int{</span><br><span class="line"> get {</span><br><span class="line"> print("get c")</span><br><span class="line"> return 3</span><br><span class="line"> }</span><br><span class="line"> set{</span><br><span class="line"> print("set c:\(newValue)")</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> //2添加计算属性</span><br><span class="line"> var isAdult:Bool{</span><br><span class="line"> get{</span><br><span class="line"> return self.age ?? 0 > 2</span><br><span class="line"> }</span><br><span class="line"> set{</span><br><span class="line"> if newValue {</span><br><span class="line"> self.age = 2</span><br><span class="line"> }else{</span><br><span class="line"> self.age = 0</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> //3使用AssociatedObject添加存储属性</span><br><span class="line"> var name:String {</span><br><span class="line"> get{</span><br><span class="line"> return objc_getAssociatedObject(self, &animalName) as! String</span><br><span class="line"> }</span><br><span class="line"> set{</span><br><span class="line"> objc_setAssociatedObject(self, &animalName, newValue, .OBJC_ASSOCIATION_ASSIGN)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure>调用示例<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">let animal = Animal()</span><br><span class="line">animal.age = 3</span><br><span class="line">print("\(animal.age)")//Optional(3)</span><br><span class="line">animal.name = "AA"</span><br><span class="line">animal.isAdult = true</span><br><span class="line">print("-----")</span><br><span class="line">print("\(animal.age)")//Optional(2)</span><br><span class="line">print("\(animal.name)")//AA</span><br><span class="line">Animal.c = 6</span><br><span class="line">print(Animal.c)</span><br></pre></td></tr></table></figure><img src="https://upload-images.jianshu.io/upload_images/6695792-ce68ac37a0fe7081.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="调用结果"><br>1,这里需要解释一下官方文档中虽然介绍<code>extension</code>不能添加存储属性,但是依旧可以利用<code>AssociatedObject</code>来达到添加存储属性的效果<br>2,在类和结构体中添加计算属性,“存储属性”可以按照以上方式,但是在<code>protocol</code>中又会是何种情况呢?我们知道<code>protocol</code>中可以定义属性和方法,而遵循该<code>protocol</code>的类或结构体就必须实现其中的方法,添加其中的属性(Optional除外)。如果在定义<code>protocol</code>时并没有申明子类必须添加某个属性,而你通过拓展添加了一个存储属性,那你之前遵循过此协议的子类岂不是都不能编译通过了。因此在拓展协议时只能添加<code>Optional</code>属性。<h5 id="在协议中添加optional属性"><a href="#在协议中添加optional属性" class="headerlink" title="在协议中添加optional属性"></a>在协议中添加<code>optional</code>属性</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">protocol P{</span><br><span class="line"> var name:String{ get set}</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line">extension P{</span><br><span class="line"> //添加静态计算属性</span><br><span class="line"> static var c:Int{</span><br><span class="line"> get {</span><br><span class="line"> print("get c")</span><br><span class="line"> return 3</span><br><span class="line"> }</span><br><span class="line"> set{</span><br><span class="line"> print("set c:\(newValue)")</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> //添加计算属性</span><br><span class="line"> var temp:Bool{</span><br><span class="line"> get{</span><br><span class="line"> return true</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> set{</span><br><span class="line"> print("set temp:\(newValue)")</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> //使用AssociatedObject添加存储属性</span><br><span class="line"> var words:String? {</span><br><span class="line"> get{</span><br><span class="line"> return objc_getAssociatedObject(self, &animalName) as? String</span><br><span class="line"> }</span><br><span class="line"> set{</span><br><span class="line"> objc_setAssociatedObject(self, &animalName, newValue, .OBJC_ASSOCIATION_ASSIGN)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">class B : P{</span><br><span class="line"> var name: String = ""</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><img src="https://upload-images.jianshu.io/upload_images/6695792-5469438a0298656d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="调用结果"></li></ul><h4 id="二、定义实例方法和类型方法"><a href="#二、定义实例方法和类型方法" class="headerlink" title="二、定义实例方法和类型方法"></a>二、定义实例方法和类型方法</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">extension String {</span><br><span class="line"> func fetchDate(_ format :String = "YYYY-MM-dd HH:mm:ss") ->Date?{</span><br><span class="line"> let dateFormater = DateFormatter.init()</span><br><span class="line"> dateFormater.dateFormat = format</span><br><span class="line"> </span><br><span class="line"> let date = dateFormater.date(from: self)</span><br><span class="line"> return date</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>1,在结构体和类中添加拓展方法应该是日常开发中最为常见的<br>2,在拓展类时添加实例方法既可以用<code>class</code>修饰也可以使用<code>static</code>修饰,而在结构体和协议中只能使用<code>static</code>修饰,因为<code>Class methods are only allowed within classes</code></p><h4 id="三、提供新的构造器"><a href="#三、提供新的构造器" class="headerlink" title="三、提供新的构造器"></a>三、提供新的构造器</h4><h5 id="1,给结构体添加新的构造器"><a href="#1,给结构体添加新的构造器" class="headerlink" title="1,给结构体添加新的构造器"></a>1,给结构体添加新的构造器</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">struct H{</span><br><span class="line"> var num1:Int?</span><br><span class="line"> var num2:Int?</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">extension H{</span><br><span class="line"> init(num1:Int,num2:Int) {</span><br><span class="line"> self.num1 = num1</span><br><span class="line"> self.num2 = num2</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> init(num1:Int){</span><br><span class="line"> self.num1 = num1</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">let h = H(num1: 2, num2: 3)</span><br><span class="line">print(h.num1)//Optional(2)</span><br><span class="line">print(h.num2)//Optional(3)</span><br></pre></td></tr></table></figure><p><img src="https://upload-images.jianshu.io/upload_images/6695792-20ba07afe643a20b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="结构体构造函数"><br>从上图的代码提示中可以看到<code>struct</code> <code>H</code>在初始化时有系统默认生成的一个无参构造函数和一个带有所有属性的构造函数,以及我们在<code>extension</code>中添加的两个构造函数</p><h5 id="2,给类添加新的构造器"><a href="#2,给类添加新的构造器" class="headerlink" title="2,给类添加新的构造器"></a>2,给类添加新的构造器</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">extension UIColor{</span><br><span class="line"> /// hexColor</span><br><span class="line"> convenience init(hex: String , alpha: CGFloat = 1) {</span><br><span class="line"> let scanner = Scanner(string: hex)</span><br><span class="line"> scanner.scanLocation = 0</span><br><span class="line"> </span><br><span class="line"> var rgbValue: UInt64 = 0</span><br><span class="line"> </span><br><span class="line"> scanner.scanHexInt64(&rgbValue)</span><br><span class="line"> </span><br><span class="line"> let r = (rgbValue & 0xff0000) >> 16</span><br><span class="line"> let g = (rgbValue & 0xff00) >> 8</span><br><span class="line"> let b = rgbValue & 0xff</span><br><span class="line"> </span><br><span class="line"> self.init(</span><br><span class="line"> red: CGFloat(r) / 0xff,</span><br><span class="line"> green: CGFloat(g) / 0xff,</span><br><span class="line"> blue: CGFloat(b) / 0xff, alpha: alpha</span><br><span class="line"> )</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>与<code>struct</code>不同的是在拓展类时只能添加便利构造器</p><h4 id="四、定义下标"><a href="#四、定义下标" class="headerlink" title="四、定义下标"></a>四、定义下标</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">extension String</span><br><span class="line">{</span><br><span class="line"> /// 返回索引为index的字符,未找到返回空</span><br><span class="line"> subscript(index: Int) -> String {</span><br><span class="line"> let range = 0...self.count - 1</span><br><span class="line"> if range.contains(index){</span><br><span class="line"> let s = self.index(startIndex, offsetBy: index)</span><br><span class="line"> let e = self.index(startIndex, offsetBy: index + 1)</span><br><span class="line"> return String(self[s..<e])</span><br><span class="line"> }</span><br><span class="line"> return ""</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">let str1 = "12345"</span><br><span class="line">print(str1[-3])// ""</span><br><span class="line">print(str1[3])// "4"</span><br></pre></td></tr></table></figure><p>类同理</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">class People{</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">extension People{</span><br><span class="line"> subscript(index: Int) -> String {</span><br><span class="line"> </span><br><span class="line"> return "AA"</span><br><span class="line"> }</span><br><span class="line"> subscript(a:String,b:Int) -> Int{</span><br><span class="line"> return 3</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">let p = People()</span><br><span class="line">print(p[2])//AA</span><br><span class="line">print(p["SS",0])//3</span><br></pre></td></tr></table></figure><p><code>ps:</code>对于类拓展下标的功能写完我真的是给<code>Swift</code>跪了,可以自定义参数,自定义返回值。上面拓展<code>String</code>的下标访问还可以理解,对于给类添加下标访问方法目前我还没有发现有什么妙用,如果有什么好案例还望不吝赐教。</p><h4 id="五、定义嵌套类型"><a href="#五、定义嵌套类型" class="headerlink" title="五、定义嵌套类型"></a>五、定义嵌套类型</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">class People{</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">extension People{</span><br><span class="line"> enum gender{</span><br><span class="line"> case man</span><br><span class="line"> case woman</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">// 使用</span><br><span class="line">People.gender.man</span><br></pre></td></tr></table></figure><h4 id="六、使一个已有类型符合某个协议"><a href="#六、使一个已有类型符合某个协议" class="headerlink" title="六、使一个已有类型符合某个协议"></a>六、使一个已有类型符合某个协议</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">extension MAOrderListSecondViewController :UITableViewDelegate,UITableViewDataSource{</span><br><span class="line"> </span><br><span class="line"> func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {</span><br><span class="line"> return dataSource.count</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {</span><br><span class="line"> return UITableView.automaticDimension</span><br><span class="line"> }</span><br><span class="line"> //....</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在开发中我经常将某个类需要遵循的协议使用<code>extension</code>分割开来以提高代码的可读性</p><h4 id="七、拓展协议添加where从句"><a href="#七、拓展协议添加where从句" class="headerlink" title="七、拓展协议添加where从句"></a>七、拓展协议添加<code>where</code>从句</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">protocol MAViewProtocol {</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">extension MAViewProtocol where Self:UIView{</span><br><span class="line"> func getString() -> String{</span><br><span class="line"> return "String"</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">class MATestColor:UIColor,MAViewProtocol{</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">class MATestView:UIView,MAViewProtocol {</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">let view = MATestView()</span><br><span class="line">view.getString()</span><br><span class="line">let color = MATestColor()</span><br><span class="line">color.getString()</span><br></pre></td></tr></table></figure><p>上面的代码段中<code>color.getString()</code>是无法通过编译的。首先我在<code>MAViewProtocol</code>的拓展中添加了<code>getString()</code>方法虽然<code>MATestColor</code>和<code>MATestView</code>都遵循了<code>MAViewProtocol</code>,但是我在拓展时添加了<code>where</code>从句<code>where Self:UIView</code>。意思为只有是<code>UIView</code>的子类才能使用该拓展中的方法,而<code>MATestColor</code>继承自<code>UIColor</code>因此无法调用<code>getString()</code>方法</p><h4 id="八、通过拓展协议实现命名空间"><a href="#八、通过拓展协议实现命名空间" class="headerlink" title="八、通过拓展协议实现命名空间"></a>八、通过拓展协议实现命名空间</h4><p>从事iOS开发的同学应该不会对<code>Kingfisher</code>中的<code>kf</code>,<code>RxSwift</code>中<code>rx</code>感到陌生</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line">public struct Reactive<Base> {</span><br><span class="line"> /// Base object to extend.</span><br><span class="line"> public let base: Base</span><br><span class="line"></span><br><span class="line"> /// Creates extensions with base object.</span><br><span class="line"> ///</span><br><span class="line"> /// - parameter base: Base object.</span><br><span class="line"> public init(_ base: Base) {</span><br><span class="line"> self.base = base</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/// A type that has reactive extensions.</span><br><span class="line">public protocol ReactiveCompatible {</span><br><span class="line"> /// Extended type</span><br><span class="line"> associatedtype ReactiveBase</span><br><span class="line"></span><br><span class="line"> @available(*, deprecated, renamed: "ReactiveBase")</span><br><span class="line"> typealias CompatibleType = ReactiveBase</span><br><span class="line"></span><br><span class="line"> /// Reactive extensions.</span><br><span class="line"> static var rx: Reactive<ReactiveBase>.Type { get set }</span><br><span class="line"></span><br><span class="line"> /// Reactive extensions.</span><br><span class="line"> var rx: Reactive<ReactiveBase> { get set }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">extension ReactiveCompatible {</span><br><span class="line"> /// Reactive extensions.</span><br><span class="line"> public static var rx: Reactive<Self>.Type {</span><br><span class="line"> get {</span><br><span class="line"> return Reactive<Self>.self</span><br><span class="line"> }</span><br><span class="line"> // swiftlint:disable:next unused_setter_value</span><br><span class="line"> set {</span><br><span class="line"> // this enables using Reactive to "mutate" base type</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> /// Reactive extensions.</span><br><span class="line"> public var rx: Reactive<Self> {</span><br><span class="line"> get {</span><br><span class="line"> return Reactive(self)</span><br><span class="line"> }</span><br><span class="line"> // swiftlint:disable:next unused_setter_value</span><br><span class="line"> set {</span><br><span class="line"> // this enables using Reactive to "mutate" base object</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这段代码是从<code>RxSwift</code>框架中截取出来,目前对于我来说只是知其然不知其所以然,后续再慢慢深究吧。</p><blockquote><p>参考文献<br><a href="https://docs.swift.org/swift-book/LanguageGuide/Extensions.html#//apple_ref/doc/uid/TP40014097-CH24-ID152" target="_blank" rel="noopener">https://docs.swift.org/swift-book/LanguageGuide/Extensions.html#//apple_ref/doc/uid/TP40014097-CH24-ID152</a><br><a href="https://www.runoob.com/swift/swift-extensions.html" target="_blank" rel="noopener">https://www.runoob.com/swift/swift-extensions.html</a></p></blockquote>]]></content>
<summary type="html">
<p>Swift中可以对类,结构体,协议,枚举进行拓展添加新的功能<br>考虑到本篇博文中的篇幅,关于枚举的拓展将在下一篇介绍<code>ps:</code>基于Swift 5<br>Swift 中的扩展可以:</p>
<ul>
<li>一、添加计算型属性和计算型静态属性</li>
<li>二、定义实例方法和类型方法</li>
<li>三、提供新的构造器</li>
<li>四、定义下标</li>
<li>五、定义和使用新的嵌套类型</li>
<li>六、使一个已有类型符合某个协议
</summary>
<category term="Swift" scheme="http://yoursite.com/categories/Swift/"/>
<category term="Swift" scheme="http://yoursite.com/tags/Swift/"/>
<category term="Extension" scheme="http://yoursite.com/tags/Extension/"/>
</entry>
<entry>
<title>Moya网络请求封装</title>
<link href="http://yoursite.com/2020/04/30/2020/04/moyawrap/"/>
<id>http://yoursite.com/2020/04/30/2020/04/moyawrap/</id>
<published>2020-04-30T09:41:00.000Z</published>
<updated>2020-04-30T09:42:13.905Z</updated>
<content type="html"><![CDATA[<blockquote><p>最近项目中使用了Moya来做网络请求,于是对其简单封装一下以方便使用<br><a href="https://github.com/Moya/Moya" target="_blank" rel="noopener">Moya: https://github.com/Moya/Moya</a></p></blockquote><a id="more"></a><h3 id="自定义插件"><a href="#自定义插件" class="headerlink" title="自定义插件"></a>自定义插件</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">final class RequestLogPlugin: PluginType{</span><br><span class="line"> </span><br><span class="line"> func willSend(_ request: RequestType, target: TargetType) {</span><br><span class="line"> Log("[URL]:\(request.request!.url!.absoluteString)")</span><br><span class="line"> if(request.request?.httpBody != nil){</span><br><span class="line"> let JSONString = NSString(data:(request.request?.httpBody!)!,encoding: String.Encoding.utf8.rawValue)</span><br><span class="line"> Log("[Param:]---------------------------------[")</span><br><span class="line"> Log(JSONString!)</span><br><span class="line"> Log("[Param:]---------------------------------]")</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这里主要是添加了两个打印信息,一个请求的接口地址,一个是请求时的参数,方便在开发过程中调试。</p><h3 id="请求类"><a href="#请求类" class="headerlink" title="请求类"></a>请求类</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">import Moya</span><br><span class="line">import SwiftyJSON</span><br><span class="line"></span><br><span class="line">let MAProvider = MoyaProvider<MultiTarget>( plugins: [RequestLogPlugin()])</span><br><span class="line">struct AHNetwork {</span><br><span class="line"> </span><br><span class="line"> static func request(_ target:MultiTarget,success successCallback: @escaping (String) -> Void,failure failureCallback: @escaping (MoyaError) -> Void){</span><br><span class="line"> </span><br><span class="line"> MAProvider.request(target) { (result) in</span><br><span class="line"> switch result {</span><br><span class="line"> case let .success(response):</span><br><span class="line"> let jsonData = response.data</span><br><span class="line"> let jsonString = String.init(data: jsonData, encoding: .utf8)</span><br><span class="line"> Log("[Reponse:]---------------------------------[")</span><br><span class="line"> Log(jsonString!)</span><br><span class="line"> Log("[Reponse:]---------------------------------]")</span><br><span class="line"> successCallback(jsonString!)</span><br><span class="line"> case let .failure(error):</span><br><span class="line"> Log("[Error:]\(String(describing: error.errorDescription))")</span><br><span class="line"> failureCallback(error)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>1,定义一个<code>Provider</code>使用我们刚定义的<code>plugin</code><br>2,将请求方法都封装在AHNetwork中的<code>request</code>方法中,此方法需传入<code>target</code>,一个<code>success</code>的逃逸闭包和<code>failure</code>的逃逸闭包。<br>2,这里的<code>Log</code>函数为一个全局的打印函数,在本文最后贴出。<br>3,在这个函数内可以根据实际的业务需求添加一些需要统一处理的逻辑,比如<code>token</code>过期,错误处理之类的逻辑。</p><h3 id="API"><a href="#API" class="headerlink" title="API"></a>API</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line">import Moya</span><br><span class="line"></span><br><span class="line">public enum AHVideoAPi {</span><br><span class="line"> </span><br><span class="line"> case fetchVideoCategory</span><br><span class="line"> case fetchVideoCategoryDetail(_ id:Int)</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">extension AHVideoAPi : TargetType{</span><br><span class="line"> </span><br><span class="line"> public var baseURL: URL {</span><br><span class="line"> return URL(string: "https://api.apiopen.top")!</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public var path: String {</span><br><span class="line"> switch self {</span><br><span class="line"> case .fetchVideoCategory:</span><br><span class="line"> return "/videoCategory"</span><br><span class="line"> case .fetchVideoCategoryDetail:</span><br><span class="line"> return "/videoCategoryDetails"</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public var method: Moya.Method {</span><br><span class="line"> switch self {</span><br><span class="line"> case .fetchVideoCategory,.fetchVideoCategoryDetail:</span><br><span class="line"> return .post</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public var sampleData: Data {</span><br><span class="line"> return "{}".data(using: String.Encoding.utf8)!</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public var task: Task {</span><br><span class="line"> switch self {</span><br><span class="line"> case .fetchVideoCategory:</span><br><span class="line"> return .requestPlain</span><br><span class="line"> case .fetchVideoCategoryDetail(let id):</span><br><span class="line"> let params: [String: Any] = ["id":id]</span><br><span class="line"> return .requestParameters(parameters: params,encoding: URLEncoding.default)</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> public var headers: [String : String]? {</span><br><span class="line"> return nil</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>Api类就是Moya的常规使用,这里就不多做解释了</p><h3 id="请求案例"><a href="#请求案例" class="headerlink" title="请求案例"></a>请求案例</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">AHNetwork.request(MultiTarget(AHVideoAPi.fetchVideoCategory), success: { (_) in</span><br><span class="line"> /// do something success</span><br><span class="line">}) { (_) in</span><br><span class="line"> /// do something error</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="Log函数"><a href="#Log函数" class="headerlink" title="Log函数"></a>Log函数</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">func Log<T>(_ message:T,file:String = #file,funcName:String = #function,lineNum:Int = #line){</span><br><span class="line"> </span><br><span class="line"> #if DEBUG</span><br><span class="line"></span><br><span class="line"> let file = (file as NSString).lastPathComponent;</span><br><span class="line"></span><br><span class="line"> print("\(file):(\(lineNum))--\(message)");</span><br><span class="line"> </span><br><span class="line"> #endif </span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<blockquote>
<p>最近项目中使用了Moya来做网络请求,于是对其简单封装一下以方便使用<br><a href="https://github.com/Moya/Moya" target="_blank" rel="noopener">Moya: https://github.com/Moya/Moya</a></p>
</blockquote>
</summary>
<category term="Moya" scheme="http://yoursite.com/tags/Moya/"/>
</entry>
<entry>
<title>序</title>
<link href="http://yoursite.com/2020/04/25/2020/04/preface/"/>
<id>http://yoursite.com/2020/04/25/2020/04/preface/</id>
<published>2020-04-25T02:54:00.000Z</published>
<updated>2020-04-25T04:32:07.431Z</updated>
<content type="html"><![CDATA[<p><em>黄色的树林里分出两条路</em><br><em>可惜我不能同时涉足</em><br><em>我在那路口久久伫立</em><br><em>我向着一条路极目望去</em><br><em>直到它消失在丛林深处</em><br><em>但我却选了另外一条路</em><br><em>因此走出了这迥异的旅途</em></p><div style="text-align: right">摘自《未选择的路》</div><a id="more"></a><h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>  前面那首诗透露出的浪漫主义是令我非常神往的,所以放在了本站第一篇博客的顶部。笔者至今从事iOS开发已经三年了,三年了,开发水平依旧是平平无奇。记得刚毕业那会我给自己设定了两个目标,一个就是三年之内一定要独立开发一款自己的APP,另一个就是一个月至少更新四篇博客。如今博客压根没写几篇,APP尚未有任何雏形。笔者今天将穿上盔甲,拿起宝剑,踏上战马,再次出发。</p>]]></content>
<summary type="html">
<p><em>黄色的树林里分出两条路</em><br><em>可惜我不能同时涉足</em><br><em>我在那路口久久伫立</em><br><em>我向着一条路极目望去</em><br><em>直到它消失在丛林深处</em><br><em>但我却选了另外一条路</em><br><em>因此走出了这迥异的旅途</em></p>
<div style="text-align: right">摘自《未选择的路》</div>
</summary>
<category term="序" scheme="http://yoursite.com/tags/%E5%BA%8F/"/>
</entry>
<entry>
<title>Hello World</title>
<link href="http://yoursite.com/2020/04/21/hello-world/"/>
<id>http://yoursite.com/2020/04/21/hello-world/</id>
<published>2020-04-21T13:00:24.786Z</published>
<updated>2020-04-21T13:00:24.786Z</updated>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/" target="_blank" rel="noopener">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html" target="_blank" rel="noopener">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="noopener">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html" target="_blank" rel="noopener">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html" target="_blank" rel="noopener">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html" target="_blank" rel="noopener">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html" target="_blank" rel="noopener">Deployment</a></p>]]></content>
<summary type="html">
<p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="https://hexo.
</summary>
</entry>
</feed>