IOS異步獲取數(shù)據(jù)并刷新界面dispatch_async的使用方法

個(gè)人收藏

在ios的開發(fā)和學(xué)習(xí)中多線程編程是必須會(huì)遇到并用到的记劈。

java中以及Android開發(fā)中,大量的后臺(tái)運(yùn)行,異步消息隊(duì)列浓镜,基本都是運(yùn)用了多線程來實(shí)現(xiàn)溃列。

同樣在,在ios移動(dòng)開發(fā)和Android基本是很類似的一種模型膛薛。

但是很多時(shí)候,在應(yīng)用開發(fā)中听隐,我們會(huì)發(fā)現(xiàn)本身并沒有自己編碼去處理一些并發(fā)的事件,去開辟新的子線程等等相叁。

(雖然一般的調(diào)用sdk發(fā)起一個(gè)網(wǎng)絡(luò)請(qǐng)求遵绰,系統(tǒng)都是會(huì)默認(rèn)給你新起一個(gè)線程去處理的)。

整個(gè)程序看上去基本就是在Main線程中執(zhí)行增淹。

確實(shí)也是這樣的一種現(xiàn)象椿访,因?yàn)槲覀兓径际窃诓僮骺丶牟季郑瑢?duì)控件數(shù)據(jù)添加虑润,對(duì)于UI對(duì)象的更新都是在主線程的進(jìn)行成玫。

即便等下我們看到我們開啟了一個(gè)新的子線程用來獲取處理數(shù)據(jù),最后還是需要通過通知UI主線程來刷新拳喻。

當(dāng)然了哭当,ios本身也是和大部分語言一樣,有NSThread線程類(我們都知道java中我們用到這個(gè)類)冗澈。

這些系統(tǒng)比較底層的api類钦勘,可以被我用來書寫自己的并發(fā)線程和操作隊(duì)列。

學(xué)過Android的我們都知道Handler亚亲,Looper這個(gè)概念彻采,Looper說白了就是一個(gè)主線程的消息循環(huán)隊(duì)列,handler一般理解就是用于子線程和UI主線程一些數(shù)據(jù)交互捌归。

看了下ios的GCD特性肛响,發(fā)現(xiàn)他們之間頗有幾分相似。

1.下面來看下如何使用gcd編程的異步Objective-c代碼

dispatch_async(dispatch_get_global_queue(0, 0), ^{

// 處理耗時(shí)操作的代碼塊...

//通知主線程刷新

dispatch_async(dispatch_get_main_queue(), ^{

//回調(diào)或者說是通知主線程刷新惜索,

});

});

復(fù)制代碼

dispatch_async開啟一個(gè)異步操作特笋,第一個(gè)參數(shù)是指定一個(gè)gcd隊(duì)列,第二個(gè)參數(shù)是分配一個(gè)處理事物的程序塊到該隊(duì)列巾兆。

dispatch_get_global_queue(0, 0)猎物,指用了全局隊(duì)列。

一般來說系統(tǒng)本身會(huì)有3個(gè)隊(duì)列角塑。

global_queue霸奕,current_queue,以及main_queue.

獲取一個(gè)全局隊(duì)列是接受兩個(gè)參數(shù),第一個(gè)是我分配的事物處理程序塊隊(duì)列優(yōu)先級(jí)吉拳。分高低和默認(rèn),0為默認(rèn)2為高适揉,-2為低

Objective-c代碼

#define DISPATCH_QUEUE_PRIORITY_HIGH? ???2

#define DISPATCH_QUEUE_PRIORITY_DEFAULT??0

#define DISPATCH_QUEUE_PRIORITY_LOW? ???(-2)

復(fù)制代碼

處理完事物后留攒,需要將結(jié)果返回給或者是刷新UI主線程煤惩,同樣,和上面一樣炼邀,抓取主線程魄揉,程序塊操作。

//天啊拭宁,手賤不小心點(diǎn)到了home間洛退,會(huì)退后發(fā)現(xiàn)沒保存~~~寫的并發(fā)一塊內(nèi)容都沒了!=鼙辍兵怯!

二:GCD之并發(fā)概念

其實(shí)對(duì)于編程中,我們一直提及到的幾個(gè)概念腔剂,同步媒区,異步,并發(fā)掸犬,鎖等袜漩。

有時(shí)覺得一下子還真說不清。

下面我們以上面提到的圖片加載來看下這3個(gè)概念我的理解

1同步:

Objective-c代碼

for (int i = 0 ; i < 10; i++) {

UIImage *img = [self getImgeWith:[urlArr objectForIndex:i]];

[myImgV[i] setImage:img];

}

復(fù)制代碼

假設(shè)我要加載10個(gè)圖片湾碎,我現(xiàn)在擁有這些圖片的資源地址宙攻,保存在一個(gè)數(shù)組中。

我們先以獲取第一張圖片來舉例:

同步執(zhí)行的概念就是介褥,我獲取完第一張圖片的座掘,

執(zhí)行了for循環(huán)第一句返回了img后,我才能執(zhí)行第二句呻顽,UI界面的刷新雹顺。

如果第一句返回的時(shí)間需要10秒,那我程序的響應(yīng)就仿佛一直卡在這里一樣廊遍,我無法進(jìn)行其他操作嬉愧。必須等它返回!喉前!

因此没酣,同步的一個(gè)很好理解的感念就是,一步走到黑卵迂。

2.異步

for (int i = 0 ; i < 10; i++) {

dispatch_async(dispatch_get_global_queue(0, 0), ^{

// 處理耗時(shí)操作的代碼塊...

UIImage *img = [self getImgeWith:[urlArr objectForIndex:i]];

//通知主線程刷新

dispatch_async(dispatch_get_main_queue(), ^{

//回調(diào)或者說是通知主線程刷新裕便,

[myImgV[i] setImage:img];

});

});

復(fù)制代碼

看了這代碼,我們會(huì)說见咒,異步操作那個(gè)假設(shè)還是要10秒啊偿衰,總體看來,執(zhí)行一張圖片的時(shí)間加載還是要在10秒左右啊,

貌似異步?jīng)]什么鳥用么下翎。但是缤言,別忽略了其中一點(diǎn),也黑絲核心的一點(diǎn)视事,此時(shí)我們圖片獲取操作放在里一個(gè)線程隊(duì)列里胆萧,

此刻,雖然我們看著圖片的加載還是需要10秒才會(huì)出來俐东,但是跌穗,在這10秒期間,我們的UI主線程是可以操作的虏辫,比如界面上有個(gè)按鈕蚌吸,你是可以按的

而不是如上面的同步,在10面期間乒裆,我是只能干等著套利,什么都做不了。

異步的核心概念就是一個(gè)新線程鹤耍,一個(gè)消息回調(diào)通知肉迫。

3.并行

我們還是以上代碼為例。前面我強(qiáng)調(diào)了稿黄,我們只看一張圖片的加載喊衫,現(xiàn)在,回到我們第一眼看到代碼的思維上去杆怕,

一個(gè)for循環(huán)族购。其實(shí)上面代碼過后,我是創(chuàng)建了10個(gè)異步線程陵珍。

好吧寝杖,到此,我們應(yīng)該明白這三個(gè)概念了互纯。

同步瑟幕,其實(shí)我前面的例子舉得有些局限,就是這個(gè)例子本身就說明不需要同步執(zhí)行留潦,然后給大家大感覺是

同步是編程中一個(gè)忌諱點(diǎn)一樣只盹,其實(shí)不然,很多時(shí)候兔院。我們真是需要同步來做一些限制(比如線程中提出的同步鎖殖卑?聽著就感覺有用么

雖然可能并不如我們想的那樣的運(yùn)用同步,但是至少說明這個(gè)概念同樣是有用的)

我還是以剛才那個(gè)加載圖片為例子坊萝,來個(gè)簡(jiǎn)單的說明如何運(yùn)用同步的好處孵稽。

當(dāng)然许起,我只是模擬一個(gè)同步的情況。

假設(shè)我們現(xiàn)在圖片的加載是這樣的肛冶,圖片本身為在加載前是一個(gè)默認(rèn)的圖片街氢,上面寫著,點(diǎn)擊我加載睦袖,點(diǎn)擊后會(huì)調(diào)用網(wǎng)絡(luò)加載方法,然后圖片顯示加載中荣刑,

然后我們雙擊圖片時(shí)(當(dāng)然馅笙,理論上是在加載完后)讀取圖片網(wǎng)絡(luò)圖片放大,好吧厉亏,到這里應(yīng)該能想到要表達(dá)的情況了董习。

整個(gè)流程應(yīng)該是點(diǎn)擊圖片->加載->雙擊查看。那如果成了點(diǎn)擊->加載中(以返回了圖片的作者和信息)-》雙擊圖片(通過前面請(qǐng)求返回的大圖鏈接顯示大圖)-》

完全加載返回(返回了大圖鏈接)爱只。此時(shí)我們看不到圖像的大圖了皿淋。因?yàn)槲覀儾僮髟诜祷厍傲耍簿褪钦f恬试,

很多時(shí)候窝趣,我們下一個(gè)動(dòng)作的操作必須需要用到前面一個(gè)操作的數(shù)據(jù)時(shí),我們會(huì)給他做認(rèn)為的同步編程训柴,比如加個(gè)按鈕鎖哑舒。

這是我們又會(huì)疑惑道,下一個(gè)執(zhí)行需要用到前一個(gè)執(zhí)行的幻馁,那第一個(gè)例子中的for循環(huán)的第二句不是要用到么洗鸵,這么說

他們必須要同步啊,如果你這么想了仗嗦,好巧膘滨,我們想到一塊去了~

但是,注意稀拐,前面我們到的異步是為了解決我點(diǎn)擊其他按鈕的操作火邓,而不是說更新UI操作。下載和更新UI操作在我們看來必須是同步的

這是對(duì)的钩蚊,但是那種做導(dǎo)致了系統(tǒng)本身一些監(jiān)聽事件監(jiān)聽到點(diǎn)擊處理在那個(gè)請(qǐng)求之后了贡翘,這邊的加載圖片其實(shí)要看成一次事件執(zhí)行,

因?yàn)閷?duì)于事件的這一抽象單元砰逻,其實(shí)是一種可人為定義的寬廣度鸣驱。

也就是說,一次數(shù)據(jù)獲取和圖像填充蝠咆,其實(shí)算是一個(gè)圖像獲取加載事件踊东,事件可以說包含兩個(gè)單元北滥,加載和填充。

而整個(gè)這個(gè)事件對(duì)于我們點(diǎn)擊其他按鈕并無關(guān)系闸翅,那么也就說明了無需同步再芋。

有道理啊,但是若果我們要點(diǎn)擊這個(gè)圖片呢坚冀,也就是回到剛才那個(gè)可以雙擊的假設(shè)济赎。

此處也許我么又忽略了一點(diǎn)為什么加載中我們能點(diǎn)擊雙擊呢,也就這樣的假設(shè)是獲取圖片已經(jīng)做了異步记某,但是我們下一步操作又是需要同步的

因此做了人為的同步鎖定司训。

好了,說的太多了液南,當(dāng)時(shí)至少我們明白兩點(diǎn)

異步可能是為了反正耗時(shí)操作造成的主線程堵塞壳猜,

同步是為了解決一些不必要錯(cuò)誤和麻煩。也許到這里滑凉,我們腦中會(huì)聯(lián)想到的所謂的線程安全性统扳。

其實(shí)同步以及同步鎖,卻是應(yīng)該是考慮到這樣的不必要和不安全因素畅姊。

最后在簡(jiǎn)單闡述下異步和并發(fā)關(guān)系咒钟。

其實(shí)看了上面說的,異步只是提供了一種多線程處理的概念涡匀,

并發(fā)是更像是異步的一種大規(guī)模實(shí)現(xiàn)盯腌。

就好比說,異步提出了可以用小弟去收保護(hù)費(fèi)陨瘩,收完了告訴并交給自己腕够,而我在期間做其他要做的事。

并發(fā)突然想到舌劳,異步這個(gè)很有道理啊帚湘,那我有4個(gè)地方要收,一個(gè)小弟去收甚淡,雖然我還是可以閑著做其他的事大诸,

但是小弟跑四個(gè)地方,我拿到錢所需要的時(shí)間還是和我自己去收一樣的贯卦,只不過我不用那么費(fèi)勁了资柔,還能做其他事了。

因此撵割,并發(fā)覺得應(yīng)該派四個(gè)小弟去贿堰,因?yàn)槊總€(gè)場(chǎng)地的保護(hù)費(fèi)各不相干的。(剛看了個(gè)紐約黑幫~)啡彬。

因此說羹与,異步解決了線程堵塞故硅,而并發(fā)則是在異步的基礎(chǔ)上,提高了符合特性事件的處理時(shí)間效率纵搁。

當(dāng)然吃衅,如果10個(gè)圖片本身相互間是沒什么聯(lián)系,但是腾誉,最后一個(gè)事件需要處理計(jì)算這10個(gè)圖片的總?cè)萘恐怠?/p>

那么可以用 dispatch_group_async徘层。

具體就看文檔吧。

總體來說妄辩,看了iosGCD這塊惑灵,一是讓我熟悉了block編程特性,還有是熟悉如何使用ios提供的GCD特性

來完成多線程編程眼耀。

常用的方法dispatch_async

為了避免界面在處理耗時(shí)的操作時(shí)卡死,比如讀取網(wǎng)絡(luò)數(shù)據(jù)佩憾,IO,數(shù)據(jù)庫讀寫等哮伟,我們會(huì)在另外一個(gè)線程中處理這些操作,然后通知主線程更新界面妄帘。

用GCD實(shí)現(xiàn)這個(gè)流程的操作比前面介紹的NSThread ?NSOperation的方法都要簡(jiǎn)單楞黄。代碼框架結(jié)構(gòu)如下:

[cpp]view plaincopy

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,?0),?^{

//?耗時(shí)的操作

dispatch_async(dispatch_get_main_queue(),?^{

//?更新界面

});

});

如果這樣還不清晰的話,那我們還是用上兩篇博客中的下載圖片為例子抡驼,代碼如下:

[cpp]view plaincopy

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,?0),?^{

NSURL?*?url?=?[NSURL?URLWithString:@"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"];

NSData?*?data?=?[[NSData?alloc]initWithContentsOfURL:url];

UIImage?*image?=?[[UIImage?alloc]initWithData:data];

if(data?!=?nil)?{

dispatch_async(dispatch_get_main_queue(),?^{

self.imageView.image?=?image;

});

}

});

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鬼廓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子致盟,更是在濱河造成了極大的恐慌碎税,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馏锡,死亡現(xiàn)場(chǎng)離奇詭異雷蹂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)杯道,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門匪煌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人党巾,你說我怎么就攤上這事萎庭。” “怎么了齿拂?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵驳规,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我创肥,道長(zhǎng)达舒,這世上最難降的妖魔是什么值朋? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮巩搏,結(jié)果婚禮上昨登,老公的妹妹穿的比我還像新娘。我一直安慰自己贯底,他們只是感情好丰辣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著禽捆,像睡著了一般笙什。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胚想,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天琐凭,我揣著相機(jī)與錄音,去河邊找鬼浊服。 笑死统屈,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的牙躺。 我是一名探鬼主播愁憔,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼孽拷!你這毒婦竟也來了吨掌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤脓恕,失蹤者是張志新(化名)和其女友劉穎膜宋,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體进肯,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡激蹲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了江掩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片学辱。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖环形,靈堂內(nèi)的尸體忽然破棺而出策泣,到底是詐尸還是另有隱情,我是刑警寧澤抬吟,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布萨咕,位于F島的核電站,受9級(jí)特大地震影響火本,放射性物質(zhì)發(fā)生泄漏危队。R本人自食惡果不足惜聪建,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望茫陆。 院中可真熱鬧金麸,春花似錦、人聲如沸簿盅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽桨醋。三九已至棚瘟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工篡殷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人禀苦。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像遂鹊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蔗包,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容