! {# _0 n) S, P3 A( S6 B! G i
本文由yake_099(博客)翻译自raywenderlich,作者:Joshua Greene2 u& _( W$ \- B& m7 g
9 J# y; @! W$ x1 X
原文:How to Use CocoaPods with Swift- r( @! C2 l3 S1 c- R
8 p9 i- F9 \" g6 x* G; z
最近关于CocoaPods有很多的议论。你可能从别的开发者那里听到过,或者在Github的目录中看到过。如果你之前从来没有用过,你可能会问,"CocoaPods到底是什么?"# j" d9 s& S7 E# [, A* @ e$ p. ~
它不是神秘的亚马逊区域的部落人用手捡出来的生可可的豆荚,肯定不是!让CocoaPods website来回答可能是最好的:
) z3 _& H* r/ x* h( V CocoaPods是Cocoa项目的依赖管理工具。它有上千个能帮你优雅地扩充自己项目的库。; e' o% N) d( [+ x0 h: g& A8 H0 C
优雅地扩展项目听起来很令人好奇,但是什么是依赖管理工具呢?你为什么会需要它呢?
& y1 w% F$ ^3 \7 F" b, ~2 }* R 无论你正在创建一个什么样的app,你都有可能会用到别的开发者的代码,无论是以框架的形式还是库的形式。你可能很熟悉UIKit和Foundation,这两个都是苹果提供的框架。$ g9 w; ?7 n0 e0 m. x0 V: V
在这个教程中,你将会:& O# E& x* q: q2 E
% X$ f- o' X% b H 了解为什么要和第三方库做朋友$ ?' n( d7 U6 v! Q0 h
]. p" ~$ c- N3 m/ S, e9 S 安装CocoaPods9 G' M \3 u8 n, j6 ]
/ D6 N- N. i1 L" J& K+ ?' G 在一个starter项目中使用CocoaPods
- Y- e( }% Y2 N* T
+ G) L; O- Z& @, D5 @6 j 安装使用并修改依赖关系文件来提高用户体验( j+ t5 J6 E: Z
+ [/ |" Q+ I: l6 I6 t; L+ y 了解语义化版本控制2 V+ c. S# v" u/ X# I7 x, n
为什么库是你的朋友
; N& |6 O) e- ~' V 尽管你并不一定非要使用第三方库和框架,但是它们确实能节省你很多的时间,可以让你集中注意力在优化自己的app上,而不是敲无数行的你本不需要写的代码。0 z6 k5 @9 P/ H3 J5 N v* y
你可以不通过依赖管理工具来使用第三方库和框架,我们网站提供了关于这种使用方式的实践性的教程。例如,这是我们的Alamofire教程和SwiftyJSON教程。
: _6 `: @% p1 Y9 v2 l4 Y, }- Y 不使用依赖管理工具,你可以简单地通过手动方式将每个库添加到你的工程里面。然而,这个方法有几个缺点:7 q+ ^7 I3 R& U) p! z3 [
# J9 \; K4 }, K6 q" \+ R1 F8 d/ H/ A 更新一个库到新的版本可能会很麻烦,尤其是一个库依赖于另外一个库的情况,那么就必须将这几个库全部更新。1 m* N8 G) Q+ P
+ X$ Z+ E K& [0 v
在项目中添加三方库可能会需要在代码中做一些本地的修改,这使得之后更新版本更加困难。- x/ u1 X( e& \0 P- X& [8 ^
+ k; |2 K+ J7 p6 h 判断你的app中用到的库的当前版本也是一件困难的事,尤其是当你没有提前记录下来的时候。
. j4 n0 b4 M. h" q V8 v( K
7 p0 @% _1 x6 j3 U; d 如果没有一个中央位置来查看所有可用库的话,查找新库也是一件很困难的事。
9 g( m: W7 f) M* J( F CocoaPods帮你克服以上问题甚至更多别的问题。它抓取库代码,解决库之间的依赖性问题,帮你查找并发现新的库,甚至以最简便的方式为你的项目配置正确的环境。; b2 s* }- `! |8 _0 w( \* Z) u- F1 V# T
前提/ b% E) K( Y- H3 f. Y5 i% u# e
这篇教程要求你熟悉基础的iOS和Swift开发。如果你完全不了解iOS或者Swift,那么在看这篇教程之前,你最好看下我们网站上一些其他文章或者视频教程,然后再回来看这篇。或者是深入来学习iOS Apprentice。
3 P# J# \7 L* T; o3 } 这篇教程也包含了使用了Core Graphics的一些类。了解Core Graphics是一件有利的事,但不是必须的。如果你想学习更多关于Core Graphics的知识,请阅读我们的Modern Core Graphics With Swift系列。. \# @9 k) N/ C7 {
这篇教程要求Xcode 6.3和Swift 1.2.
; N& E1 m4 U3 G8 N9 x7 ?4 V9 [ 开始- ^ V! _% M5 f, ] f2 b: o a
首先你需要安装CocoaPods。幸运的是,CocoaPods被建立在Ruby上,而最近的Mac OS X版本带有Ruby。这自从OS X 10.7之后就实现了。$ o* T/ T; _7 ?6 l. a4 J
打开终端并且输入以下命令行:sudo gem install cocoapods6 Q2 a5 z3 ~8 g5 M
当要求的时候输入你的密码。终端的输出结果看起来应该是这样的:
9 A, S: u9 K" w @$ z' I
% j2 y; Q; `5 R# r8 E 你必须使用sudo来安装CocoaPods,但是安装后就无需再使用了。9 x: w4 A$ T& e o! p5 c, H
% m0 f) g' d( T 最后,在终端输入以下命令行来完成设置:pod setup --verbose2 V) |; `- n* T
这个过程可能需要几分钟的时间,因为它将CocoaPods Master Specs repository克隆到了你电脑上的~/.cocoapods/目录下。1 I, v. W6 ?6 J2 L4 G" B4 E( G0 U
verbose选项记录下了进程运行时的进展,能让你看到进程而不是一个僵在那里的屏幕。# s' F$ L" z% p( H/ z1 N1 k
太好了,现在你开始设置来使用CocoaPods了。" n/ k) L4 o0 M
1 K }2 [0 P: E5 N6 P7 u3 v9 R$ [1 | 代码时间!' K7 D8 P/ d& f% t ~* V, A7 [5 o
为客户Ice Cream Shop, Inc.开发一款App. n' @% k+ [: _/ j' B4 C' X
你的首要客户是Ice Cream Shop, Inc。他们的冰淇淋太受欢迎了以至于不能在柜台接收用户订单了。他们雇佣你来做一个漂亮的iOS应用,那样就能让用户在他们的iPhone上下订单了。
' s G1 u2 U3 K 你开始开发app了,并且进展得还不错。在这里下载开始程序。4 Z5 f7 l6 \" d; v! t: s
打开IceCreamShop.xcodeproj,然后运行,你会看到一个非常好吃的香草冰淇淋。
2 k( [3 C7 ?% k; e6 F
. A' ^/ ~/ P; P* T8 ^ 用户应该能从这个屏幕中选择冰淇淋的口味,但是还不太可能,因为你还没有完成这个功能。
9 e0 y$ O b( m# E 从Views/Storyboards&Nibs中打开Main.storyboard来看app的布局。现在我们来快速整体地看一下这个app的核心,"选择你的口味"那一屏:
! x) l v9 ?: y, v0 j0 c& p7 u
8 j5 h5 X7 {# j) W2 c2 H6 ]9 T0 ?1 d# W3 x0 d- G: {2 V
PickFlavorViewController处理用户交互,例如,用户选择了冰淇淋的一种口味。( C3 N1 c. v8 Z$ J
" ?' f, T! g% w* d# q/ Q
: i# o/ B# g$ a; I; y* N& _ PickFlavorDataSource是collection view所展示的不同冰淇淋口味的数据源。( l9 U; c* g2 |, Z! w
8 z2 j4 ]8 H: W5 f, X( J0 { IceCreamView是一个自定义的view,可以用来展示冰淇淋圆锥形的蛋卷,并且它以Flavor model来支撑。
3 R7 B# w( D5 B% J. u+ b2 l, V. A+ k4 v& k6 l8 Z5 \2 F9 R: k
ScoopCell是一个自定义的collectionviewcell,它包含了一个ScoopView,这个view也是以Flavor model来支撑的。
9 _( D6 {7 M: ]6 i6 F1 y2 m9 W 由于每个冰淇淋店一般都会有一些招牌口味,每个也有他们本地的风味。因此,Flavor的实例中包含的数据需要通过web service来提供。( B" h' ]: r# p
然而,这还没有回答问题,"为什么用户不能选择一个冰淇淋口味?"
3 e2 W, J0 U8 X* ~+ P- j c5 G) O 在Controllers这个分组下面,打开PickFlavorViewController.swift,你会看到一个备用的方法:- Z6 L- r. ]! N$ n/ N
private func loadFlavors() {
8 L) M5 w# [# J8 a' R! f, U // Implement this}1 \# |, Q0 X/ Z( h3 s$ d
哈哈,这里面没有口味,你需要实现它。* F: C& b/ e" k! ?8 {1 w
你可以使用NSURLConnection或NSURLSession并用你自己写的网络类,这儿还有一个更简单的办法:Alamofire,一个开源的网络库。# l6 S" k6 b. i$ a; c$ f
你可能想就这么把它下载下来并将文件拖拽到工程里面。然而,那是很麻烦的方法。CocoaPods提供了更加优雅和灵活的解决方法。
' g; H1 Q) W, D( D, e 所以,闲话少说...5 U% ~+ W, g+ D* R& @
7 O% p. W( X7 J) O
$ m0 {. u1 i( ]7 S2 B1 O 安装你的第一个依赖管理工具1 _1 E' T3 I9 H$ N
首先你要关掉Xcode
$ @; c7 _% | M2 e1 ~7 A" j 是的,你说的对,该创建Podfile了,在那儿你要定义工程的依赖管理。
7 [, O- ~! Y. r 打开终端,用 cd 命令进入包含你IceCreamShop项目的那个目录下:cd ~/Path/To/Folder/Containing/IceCreamShop* A) |1 I+ ]* N8 X; a0 e& _$ a2 r
接下来,输入下面的命令:pod init2 r6 X% _8 p9 S5 x
这将为你的项目创建一个PodFile- c; W" c1 \6 d- b, {8 o' d
输入下面的命令行打开PodFile,并使用Xcode进行编辑:open -a Xcode Podfile
2 V, u0 Y+ c* x; C 注意:你不能使用TextEdit来编辑Podfile,因为它有可能用图形化的更有吸引力的typeset quotes代替standard quotes,这可能导致CocoaPods不能理解并抛出错误,所以最好用Xcode或者别的编程文本编辑器来编辑你的Podfile。
' Q- M, r5 n6 M7 K* m1 f 默认的podFile看起来是这样的:# Uncomment this line to define a global platform for your project# platform :ios, '6.0'
, s8 N9 u' Q; h% s, c: }target 'IceCreamShop' do 9 l. N1 D9 B, s. O* n5 C g& k0 f
end
! b! }: F3 T0 A1 atarget 'IceCreamShopTests' do ; @4 F$ f, ]5 G2 ] C
end- X2 _1 J$ Y; K/ N: W
将注释的内容替换成下面的两行:platform :ios, "8.0"use_frameworks!
, s: r1 }7 I7 r9 D 这就告诉了CocoaPods--你的项目使用的是iOS 8.0,并且将使用框架来代替静态库。* x% f( o5 m! ^5 q- H3 n
想要在Swift中使用CocoaPods,你必须明确的写出use_frameworks! 来选择使用框架。如果你忘了写这个,CocoaPods能检测到你使用使用Swift CocoaPods,你安装pods的时候就会报错。
4 L# D: _" _. L4 V" x# ` 如果你仅仅使用过Swift编程,这可能看起来有些奇怪--那是因为Podfiel实际上使用Ruby写的。你无需为了使用CocoaPods而学习Ruby,但是你要知道即使是很小的文字错误通常也会使CocoaPods出错。4 V/ C) E! X( J8 `3 h
关于“库”0 X: ~; P1 h' K" m2 K
你会看到"library"通常代指库或框架。很抱歉这个教程也在无意间混杂了这两个概念。实际上,当某人提到"Swift library",他们实际上指的是"Swift dynamic frameworks",因为swift不允许静态库。+ R3 O. t& K, u; n
你可能想知道,"库(library)和框架(frameworkd)和cocoaPod之间的不同之处"。
T- T$ d7 F& l ?5 }Cocoapod或者简写为"pod"是一种惯常的叫法,用来表示使用Cocoapods工具添加库或者框架到你的应用程序中。
) r+ K3 C0 U. V8 J iOS 8引入了动态框架,这就允许了代码、图片和其他的东西(assets)可以被一起打包。在iOS 8之前,CocoaPods被作为静态库来创建,就是很"臃肿的"二进制文件。这意味着它包含了一些代码说明设置(例如i386 for the simulator, armv7 for devices等),但是它们不允许包含任何资源,例如图片或资产。) d% }7 X+ s. Q- G' ]/ B; x
另外一个重要的区别是动态框架有命名空间类,而静态库没有。所以,如果单个项目中不同的静态库里分别有一个叫做MyTestClasses的类,那么Xcode可能不能成功创建工程因为它会因重复的标识而导致连接失败。然而,Xcode很乐意在一个工程里的不同框架下分别有一个名字相同的类。
. n1 ~4 Y* X+ [5 _6 I 为什么这很重要?不像OC,标准的Swift运行时库(runtime libraries)没有包含在iOS中!这意味着你的框架必须包含了必要的Swift运行时库。因此,用Swift语言写的pods必须以动态框架形式创建。如果苹果允许Swift静态库,那么使用同一个标准运行时依赖的不同库中将会产生重复符号。" g w6 |& ^5 c4 Q$ ?1 A w6 D/ U
幸运的是,CocoaPods为你做了这些事。它甚至能做到一次性包含需要的依赖关系。你所要做的就是在使用swift cocoaPods时记得在Podfile中包含use_frameworks! ,那就没问题了。0 f* v T/ V) n* y4 q. }8 H4 Q$ D) l
amazing,对不对?
8 e) K0 g' U" W5 B( C8 ^ H: I5 f 安装你的第一个依赖关系
/ e- Y+ v4 ~) C7 T# w 这是使用cocoapods安装你的依赖性文件的最后的时刻。将下面的内容添加到你的Podfile里面pod 'Alamofire', '1.2.3'
8 \1 o3 V4 y0 h0 x1 ]" b9 Y% ^ 这个是告诉CocoaPods你想添加1.1.4版本的Alamofire到你的工程中作为一个依赖性文件,这是写这篇教程时的最新版本。& G$ g/ v5 m) k
保存并关闭podFile
2 @1 N% K L# N9 r4 T 现在你需要告诉Cocoapods为你的工程安装依赖性文件。在终端中输入下面的命令,但是要首先确认你还在包含了IceCreamShop和Podfile的目录下:pod install# ^: w6 y2 ?! H& r) F- v9 u
你会看到输出结果与下面的类似Analyzing dependencies
Y" [" a* d2 n( m2 \* F# M! E: i! `Downloading dependencies6 x; ]( k i- i7 w
Installing Alamofire (1.1.4)Generating Pods project
7 K l) N% M8 g( v! jIntegrating client project
0 p' @* V+ S4 W# f: [! k [!] Please close any current Xcode sessions and use `IceCreamShop.xcworkspace` for this project from now on.
: E H. B0 B( V 使用Finder打开你的工程文件夹,你看看到CocoaPods创建了一个新的IceCreamShop.xcworkspace文件和一个Pods文件来存储所有的工程依赖文件。
* u6 J' H3 J+ t4 T+ Z. B, n 注意:从现在开始,就像命令行警告提示的,你必须使用workspace文件而不是project,否则你将遇到编译错误。
9 V4 k& p' e! k5 n" u 太棒了!你已经使用CocoaPods添加了你的第一个依赖管理。
# o- ^9 c& w+ h# A6 e' a1 M) J" [3 m# L2 J3 ^
?% J! E9 B. c7 M! \* R* U
使用安装好的Pods
( y6 h9 v% W' _( Q0 Y# A 如果已经打开了Xcode工程,那要关闭它并打开IceCream.xcworkspace.2 G6 e: M0 ~7 }/ Q2 U3 R0 k, r
打开PickFlavorViewController.swift,在现有的导入下添加以下代码:import Alamofire/ ^1 w, z- R0 N( B
点击command+b进行编译。如果一切都没有问题,你不会收到任何编译错误的。
8 g6 v& f/ d5 d7 ]+ X 接下来,用下面的代码代替loadFlavors()方法private func loadFlavors() {
$ [; J0 G1 }! w0 |9 k' K; k let urlString = "http://www.raywenderlich.com/downloads/Flavors.plist" // 1; q. s, y9 ]/ b
Alamofire.request(.GET, urlString, encoding: .PropertyList(.XMLFormat_v1_0, 0))
+ [0 n& B( b. | .responsePropertyList { request, response, array, error in // 2
3 X; ^/ V& d" o4 i. F; e2 ] if let error = error {' S* d1 C U( l9 r ~5 d
println("Error: \(error)") // 3) _" j H) A- `* P! e) E: A2 q
} else if let array = array as? [[String: String]] { // 41 |7 \: _7 Z( |9 S( X
if array.isEmpty {/ Z" ^3 _3 H! X/ L! Q
println("No flavors were found!") // 5
; j" d* b$ x+ p, I' a, x$ o } else { A' S! O4 R! D! U7 j" x
self.flavors = self.flavorFactory.flavorsFromDictionaryArray(array)
6 Y/ J" e6 o2 T self.collectionView.reloadData()- y, Y/ m/ K$ n3 c
self.selectFirstFlavor()! d. U+ C, J Y. _0 E( `8 `
}
7 R. e. p, X4 e- e9 Z }& T8 Q2 R& D- a6 x
}}
N& M! j) P s! f# u; n 下面是对这个过程的详细描述:0 T9 T( t' A( b: Q9 @) u
1.你用Alamofire创建了一个get请求,并下载了一个包含冰淇淋口味的plist文件。, _3 Y: R0 k$ z# C. U
2.一般你去看查看请求是否出错并解析错误。现在如果出错的话你只需要打印错误。
6 s* @+ z( ]* p; T& U 3.将一个AnyObject?类型数组转换为字典数组。
6 M, n3 X9 V" U5 l 4.如果数组是空的,你只需要打印一个错误信息。
, }3 {, e7 g1 Z3 q 5.如果一切都OK的话,你就将FlavorFactory方法创建的包含Flavor对象的数组赋值给self.flavors。这是一个同事为你写的类,是用来将装了字典类型对象的数组转换为Flavor对象。如果你喜欢的话你可以仔细看看这个工厂类,但是它对教程的其他部分不是特别重要。
7 e! m1 M. p' Q& r# x5 B! W: M' B 编译并运行!现在你可以选择一个冰淇淋口味了!
) G3 ]4 |1 z) s! `- `9 ?# B
2 f0 P H/ T8 m1 n8 G, l 选择装饰物
2 ~- [; a r$ k7 d5 Q app看起来很不错了,但是你仍然可以进行优化。: U2 [1 g' x1 Y- A
你有没有注意到app花费了几秒钟的时间来下载flavors文件?如果你的网络很快的话你可能注意不到,但是用户不会都这么幸运的。6 ]; u3 Z, ?: [5 i
为了让用户理解app现在正在加载什么内容,你可以显示一个加载指示器。MBProgressHUD是个很不错的加载指示器.并且它支持CocoaPods,多么的巧合!; m' o1 l. ~" m5 S/ Z+ G
你需要把这个加入到你的podfile里面。你现在不用通过命令行打开podfile了,你可以在工作区的pods中找到它。
, ?* O# Y: p+ i2 p/ u8 u# b
9 o5 M Z& x- ]" B2 l6 ~# h
打开podFile并在Alamofire后面加入下面几行:, j1 \# P2 |0 \
pod 'MBProgressHUD', '~> 0.9.0'
# q! x$ S! @! C* N1 I! H 保存文件,并在终端通过pod install命令来安装依赖文件,就像你之前做的那样。
# M$ z1 Q/ M0 V4 {+ c8 _ 这次发现什么不同的了吗?对,你写出了具体的版本号~>0.9.0。这儿会发生什么呢?
* a3 H6 Z% [6 l, W+ e: a Cocoapods建议所有的pods都使用语义化版本号(Semantic Versioning)。
! U3 K% y' A9 Y+ S5 u 语义化版本号, o7 s. Z9 @% [0 O
这三个数字被定义为主要的,次要的和补丁版本号。例如,版本号0.9.0会被翻译为
) U) |1 C, x' [0 V
7 E+ D3 B* _: B3 d6 v! a$ c! V
当主要的(major)版本号数字增加时, 意味着你做了一些不能兼容旧版本的更新。当你将pod升级到下一个主要版本时,你可能需要修复编译错误,否则pod可能跟之前表现得不太一样。# o, T; f+ F- a: s: c" Y
当次要(minor)版本号增加时,意味着增加了新功能,但同时兼容旧版本。当你决定升级时,你可能需要也可能不需要新的功能,但是它不应该引起编译错误或者改变现有的功能。: a7 w& Z. S8 P+ Q R
当补丁(patch)版本号增加的时候,这意味着做了bug修复。但是没有没有增加也没有改变功能。一般来说,你会希望尽快更新补丁版本到最新的版本,以便使用最新最稳定版本的pod。
' r" Q' h% h0 ?" ^# l3 d- l 最后,最高版本号(major>minor>patch)必须按照以上规则逐步增加,而较低的版本号必须从0开始。1 A' f% _' v& `% H" _
需要一个例子吗?0 _3 \4 N, J4 v4 X
考虑一个当前版本为1.2.3的pod。, B7 E- `2 g) E4 z6 f
如果做了一些不能向后兼容的改变,没有新的功能,但是修改了现有的bug,那么下一个版本是2.0.0
- L- D, G* b; T2 P- v; z# V 挑战时间
( {( u; c. E6 G+ a- d+ g 1.如果一个pod当前版本号是2.4.6,并且做了一些修复bug的改变,添加了一些向后兼容的功能,新版本应该是多少呢??
2 _( v0 n6 X* l$ U( J" \ 答案:2.5.0
^0 a. m; i* K3 k! a0 p 解释:如果修改包含向后兼容的新功能,次要版本号(monir)就要增加了,并且补丁版本号(patch)就要被置为0.5 k) Z! X8 a% P- M
2.如果一个pod的当前版本是3.5.8,并且对当前的功能做了一些改变,新版本应该是多少?7 X# m8 Y6 a2 ^6 p/ S
答案:4.0.0
' r# ]1 I8 q( Q$ ^/ [ 解释:如果改变修改了现有的功能,那么这就是不向后兼容的。所以,主要版本号(major)必须增加,而次要版本和补充版本置为0. M! q! E3 L: v' l4 W
3.如果一个pod的向前版本号是10.20.30并且只修复了一些bug,那么新版本号应该是多少?4 L& M% ]2 O4 D8 b* c
答案:10.20.31) A/ J" \2 ]" P- F( P
解释:如果只修复了bug,补充版本号(patch)就要增加了。! C% ~, _3 G# C1 ?
说了这么多,这儿有一个例外:
0 A1 a4 O" v! Z 如果一个pod的版本低于1.0.0,这就被认为是测试版,次要版本号(minor)增加可能意味着向后兼容的改变。
0 J# Q( }1 a4 }( P6 R- a 所以在MBProgressHUB中使用~>0.9.0意味着你需要安装大于或者等于0.9.0但是小于0.10.0的最新的版本.1 e0 \: |* t4 r1 h0 Z4 K) V6 [% R
这就保证了你在安装pod的时候获得了最新的bug修复,但是不会意外的拉去向后兼容的改变。这儿还有一些其他的可用操作。具体的列表,请看Podfile Syntax Reference。0 I$ r- P! Z2 ^3 ?/ s) q+ e
显示进程+ ?0 Z$ F1 \/ G+ [) q0 ]! [& |8 Q7 L
现在,回到PickFlavorViewController.swift,在其他的引用下面添加下面的内容import MBProgressHUD( |/ h+ P! A; P+ \* ~
下一步,在loadFlavors()后面加入以下方法private func showLoadingHUD() {
2 k+ n3 |; Q5 ] let hud = MBProgressHUD.showHUDAddedTo(contentView, animated: true)# E \' l* K. V- J3 J. X
hud.labelText = "Loading..."} " r" b$ t4 @2 N; Y
private func hideLoadingHUD() {6 P: P8 K! S5 J* ?
MBProgressHUD.hideAllHUDsForView(contentView, animated: true)}
! M- h* D: u3 q! i; J" ~ 现在在loadFlavors()方法中,添加下面代码:private func loadFlavors() {
* l5 Y$ Q: H$ q5 Q. D& J( J let urlString = "http://www.raywenderlich.com/downloads/Flavors.plist"
5 }* Z |+ N4 o- q6 }# ? showLoadingHUD() // .responsepropertylist { request, response, array, error in self.hideloadinghud() //
$ ]- A2 U. F# h! ? i! u 就像方法名字所表明的,showLoadingHUD()方法会在GET请求下载时产生一个MBProgressHUD的实例对象,当请求结束时hideLoadingHUD()会将HUD隐藏。由于showLoadingHUD()在闭包之外所以它不需要前置代码self。$ ~5 R8 \! s' A# _
编译运行。现在你会看到一个加载指示器: |