異步事件編程坦仍,其實(shí)并不是什么新東西了,基本所有涉及到GUI的叨襟,網(wǎng)絡(luò)請(qǐng)求的繁扎,數(shù)據(jù)庫讀寫的,都會(huì)有它的身影糊闽。
異步事件梳玫,就是說這一個(gè)代碼或者代碼塊,并不會(huì)阻塞程序的運(yùn)行右犹,程序會(huì)立即執(zhí)行下一條語句提澎,而這條語句,會(huì)在相應(yīng)的方法調(diào)用結(jié)束之后念链,執(zhí)行它自身的回調(diào)函數(shù)發(fā)送一些信號(hào)盼忌,來表明這個(gè)異步事件完成积糯。就像你約會(huì)提前1小時(shí)到見面地點(diǎn),先去買點(diǎn)東西踩點(diǎn)什么的(……)谦纱,等GF/BF到了之后短信通知你看成,你就立即回來。而不是一直在原地等到對(duì)方過來(……)
最早使用異步開發(fā)跨嘉,是在使用JavaScript來開發(fā)Web前端的時(shí)候川慌,XMLHttpRequest或者jQuery的$.ajax中,都會(huì)用到回調(diào)函數(shù)祠乃,來指明成功或者失敗之后的處理方法梦重。當(dāng)對(duì)應(yīng)的網(wǎng)絡(luò)請(qǐng)求得到響應(yīng)之后,會(huì)調(diào)用響應(yīng)的成功或者失敗的回調(diào)函數(shù)亮瓷,然后執(zhí)行里面相應(yīng)的方法琴拧,這大大提升了前端的效率,不會(huì)在網(wǎng)絡(luò)請(qǐng)求時(shí)整個(gè)頁面卡住嘱支,而且也不需要一次次輪詢看是否有響應(yīng)艾蓝,簡(jiǎn)化了代碼的復(fù)雜性。
這點(diǎn)Node.js中更為常見斗塘,不過也更能表現(xiàn)中濫用異步事件編程的問題。新人使用Node.js總會(huì)發(fā)現(xiàn)基本任何東西都是異步的亮靴,數(shù)據(jù)庫是異步的馍盟,IO文件操作是異步的,Session讀寫是異步的茧吊,甚至獲得Request對(duì)象都是異步的贞岭。這就導(dǎo)致很多人一直在嵌套回調(diào)函數(shù),導(dǎo)致了著名的Callback Hell
在Node.js中搓侄,解決方案有非常成熟的Async瞄桨,更有號(hào)稱能用同步思維寫異步的Promises,都是非常棒的解決方案讶踪。前者的本質(zhì)就是一個(gè)自動(dòng)生成回調(diào)的封裝……芯侥,后者則是一個(gè)真正意義上的全新的解決方案。
而在Swift和iOS開發(fā)中乳讥,也有必須用到異步事件編程的地方柱查。除了View層的簡(jiǎn)單UI和Controller之間的交互以外(這部分一般不需要手寫代碼處理異步交互或者順序),其他很多地方需要這些知識(shí)云石。例如網(wǎng)絡(luò)請(qǐng)求的異步調(diào)用唉工,請(qǐng)求隊(duì)列的處理(雖然可以一個(gè)網(wǎng)絡(luò)請(qǐng)求就是一個(gè)線程,但這種方法的效率不高汹忠,而且容易導(dǎo)致線程間沖突)淋硝,SQLite數(shù)據(jù)庫大量數(shù)據(jù)的讀寫雹熬,本地存儲(chǔ)的大量數(shù)據(jù)讀寫,復(fù)雜UI的渲染順序等等……這些都是需要進(jìn)行異步編程的谣膳,而不能讓同步的代碼阻塞住整個(gè)應(yīng)用或者UI竿报。
舉個(gè)例子,這里是一個(gè)UI順序加載的動(dòng)畫……
func schoolLifeClicked()
{
var mydrawerController = self.mm_drawerController //一個(gè)用TableView實(shí)現(xiàn)的應(yīng)用側(cè)邊欄抽屜View
let schoolLifeViewController:SchoolLifeViewController = SchoolLifeViewController(nibName: "SchoolLifeViewController", bundle: nil)
let navSchoolLifeViewController = CommonNavViewController(rootViewController: schoolLifeViewController)
self.mm_drawerController.toggleDrawerSide(MMDrawerSide.Left, animated: true, completion:{(complete) in
if complete{//如果成功拉出抽屜
mydrawerController.setCenterViewController(navSchoolLifeViewController, withCloseAnimation: true, completion: nil)//設(shè)置主視圖
mydrawerController.closeDrawerAnimated(true, completion:nil)//關(guān)閉抽屜
}
})//一個(gè)閉包参歹,成功后調(diào)用
}
可以看到仰楚,Swift很多時(shí)候也可以依靠回調(diào)函數(shù),把一個(gè)閉包扔進(jìn)去當(dāng)參數(shù)犬庇,然后執(zhí)行僧界,從而控制這種異步事件的流程……
但是,這種方法寫起來臭挽,就會(huì)回到和JS那種匿名函數(shù)閉包扔進(jìn)去當(dāng)參數(shù)一樣捂襟,小范圍用還可以,一旦你要進(jìn)行復(fù)雜的流程控制欢峰,比如一系列異步事件葬荷,AB同時(shí)執(zhí)行,AB同時(shí)完成后執(zhí)行C纽帖,C執(zhí)行完成后執(zhí)行D……這種控制下寫出來的代碼和JavaScript的callback hell是一樣的宠漩,難以維護(hù)。
怎么辦呢懊直?其實(shí)自己實(shí)現(xiàn)一個(gè)語法糖或者函數(shù)隊(duì)列來執(zhí)行也不難扒吁,不過這里可以推薦一下GitHub上非常厲害的庫,大家有興趣也要認(rèn)真看看源碼(雖然源碼是Objective-C的……但是慢慢來)
鏈接:
Async這個(gè)利用了OS X 10.10和iOS8的GCD技術(shù)室囊,只能在這個(gè)平臺(tái)以上
Async.legacy兼容OS X 10.9和iOS7
怎么使用呢雕崩?參考人家的Readme,用語法糖可以很簡(jiǎn)單的使用:
Async.userInitiated {
println("start")
}.main {
println("1")
}.background {
println("2")
}.background {
println("2 all the same")
}.main {
println("stop")
}
由于異步事件的特點(diǎn)融撞,所以整個(gè)輸出可能就會(huì)是
start
1
2
stop
2 all the same
不要大驚小怪哦盼铁。利用這個(gè)就可以從繁重的callback中解放出來,簡(jiǎn)單的處理異步事件的順序尝偎,并且獲得很高的性能饶火,這也是網(wǎng)絡(luò)請(qǐng)求和數(shù)據(jù)庫訪問等必須要考慮的地方……
最后,我還是多看看關(guān)于異步事件致扯,閉包的知識(shí)趁窃,對(duì)這些知識(shí)有了更深的了解,不僅對(duì)iOS開發(fā)急前,對(duì)Web開發(fā)醒陆,客戶端開發(fā),并行計(jì)算算法的實(shí)現(xiàn)等都會(huì)十分有幫助裆针。