初探在多線程中不執(zhí)行Delegate方法

初次使用案例

如果有人沒(méi)有碰到類似問(wèn)題蟆炊,可以嘗試看看。

    dispatch_queue_t queue =    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        NSString *urlString =@"http://dlsw.baidu.com/sw-search-sp/soft/9d/25765/sogou_mac_32c_V3.2.0.1437101586.dmg";
        NSString *encodeURLString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSURL *url = [NSURL URLWithString:encodeURLString];
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
        self.connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
        });

代碼很簡(jiǎn)答,就是使用NSURLConnection下載一個(gè)dmg格式的大文件吐根。不一樣的是這次我們還順帶使用到了GCD赔蒲。
若看官們還不了解GCD,簡(jiǎn)書(shū)好多大神都寫(xiě)過(guò)相關(guān)介紹GCD的文章。
下面繼續(xù)貼出關(guān)于NSURLConnection的delegate方法厘肮。

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
}

好了愧口,萬(wàn)事具備,讓我們愉快地在delegate方法中下一個(gè)斷點(diǎn)來(lái)運(yùn)行类茂。
很快我們就會(huì)發(fā)現(xiàn)這根本不會(huì)調(diào)用代理方法耍属。

開(kāi)始思考

其實(shí)思考的方向也很明確,既然是線程系的鈴,我們不妨用其來(lái)解。
我也就不賣(mài)關(guān)子巩检,原因其實(shí)就是:線程在delegate方法回調(diào)之前就已經(jīng)提前結(jié)束了厚骗。
如果這原因讓你傻眼了,別急,我來(lái)用一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明。

- (void)viewDidLoad {
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(methodOne) object:nil];
    [thread start];
    [self performSelector:@selector(methodTwo) onThread:thread withObject:nil waitUntilDone:NO];
    NSLog(@"開(kāi)始");
}

- (void)methodOne {
    NSLog(@"HI~");
}

- (void)methodTwo {
    NSLog(@"Hello~");
}

Run!!!告訴你結(jié)果:
2015-10-19 17:44:36.469 Collection[5597:373711] HI~
2015-10-19 17:44:36.469 Collection[5597:373446] 開(kāi)始

像這類問(wèn)題就是因?yàn)閷?dǎo)致了線程在執(zhí)行結(jié)束后銷毀兢哭。因此沒(méi)法快樂(lè)地說(shuō)Hello~

而這其中還涉及到一個(gè)東西:RunLoop领舰。
這里也不過(guò)多介紹,稍微簡(jiǎn)單地科普一下:

此處輸入圖片的描述
此處輸入圖片的描述
  1. 主線程默然是啟動(dòng)RunLoop的迟螺。
  2. 子線程剛創(chuàng)建的時(shí)候沒(méi)有RunLoop,需要自己手動(dòng)去添加冲秽。
  3. 主線程會(huì)在app結(jié)束后銷毀RunLoop。子線程結(jié)束后銷毀RunLoop矩父。

說(shuō)到這里也順帶說(shuō)一下,我們廣泛使用的AFNetWorking,這個(gè)第三方網(wǎng)絡(luò)請(qǐng)求框架會(huì)開(kāi)啟一個(gè)新線程來(lái)添加自己runloop事件锉桑。
無(wú)論使用NSOperation+NSURLConnection并發(fā)模型或者&GCD的并發(fā)模型,NSURLConnection遇到的這種無(wú)法回調(diào)的問(wèn)題。
AFNetWorking是這樣解決的窍株,單獨(dú)建立起一個(gè)global thread,內(nèi)置runLoop,所有的connection都由這個(gè)runloop發(fā)起民轴,回調(diào)也是它接收,不占用主線程球订,也不耗CPU資源后裸。

 + (void)networkRequestThreadEntryPoint:(id)__unused object {
    @autoreleasepool {
        [[NSThread currentThread] setName:@"AFNetworking"];
        
        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        [runLoop run];
    }
}
+ (NSThread *)networkRequestThread {
    static NSThread *_networkRequestThread = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
          _networkRequestThread =
          [[NSThread alloc] initWithTarget:self
              selector:@selector(networkRequestThreadEntryPoint:)
              object:nil];
          [_networkRequestThread start];
    });
    return _networkRequestThread;
}

動(dòng)手解決

既然不想讓線程提前結(jié)束,通常我們會(huì)用以下方式來(lái)解決。

  1. 創(chuàng)建NSTimer,掛載事件源,強(qiáng)行不讓線程提前結(jié)束辙售,當(dāng)然這種方法太Low,我選擇無(wú)視轻抱。
  2. 向創(chuàng)建的RunLoop添加NSPort,讓線程不會(huì)自己停下,然后添加判斷,來(lái)推出循環(huán)。
    不多說(shuō),上代碼旦部。
   dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
   
   dispatch_async(queue, ^{
       NSString *urlString =@"http://dlsw.baidu.com/sw-search-sp/soft/9d/25765/sogou_mac_32c_V3.2.0.1437101586.dmg";
       NSString *encodeURLString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
       NSURL *url = [NSURL URLWithString:encodeURLString];
       NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
       self.connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
       if (self.connection) {
           NSPort* port = [NSPort port];
           NSRunLoop* rl = [NSRunLoop currentRunLoop]; // Get the runloop
           [rl addPort:port forMode:NSDefaultRunLoopMode];
           [self.connection scheduleInRunLoop:rl forMode:NSDefaultRunLoopMode];
       }
       
       while(!_isFinished) {
           [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
       }
       
   });

由于本文介紹到了線程和RunLoop這兩個(gè)開(kāi)發(fā)大家樂(lè)于討論的概念
大家就自行查閱啦~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末祈搜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子士八,更是在濱河造成了極大的恐慌容燕,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件婚度,死亡現(xiàn)場(chǎng)離奇詭異蘸秘,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)醋虏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)寻咒,“玉大人,你說(shuō)我怎么就攤上這事颈嚼∶兀” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵阻课,是天一觀的道長(zhǎng)叫挟。 經(jīng)常有香客問(wèn)我,道長(zhǎng)限煞,這世上最難降的妖魔是什么抹恳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮署驻,結(jié)果婚禮上奋献,老公的妹妹穿的比我還像新娘。我一直安慰自己硕舆,他們只是感情好秽荞,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布骤公。 她就那樣靜靜地躺著抚官,像睡著了一般。 火紅的嫁衣襯著肌膚如雪阶捆。 梳的紋絲不亂的頭發(fā)上凌节,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音洒试,去河邊找鬼倍奢。 笑死,一個(gè)胖子當(dāng)著我的面吹牛垒棋,可吹牛的內(nèi)容都是我干的卒煞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼叼架,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼畔裕!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起乖订,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤扮饶,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后乍构,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體甜无,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了岂丘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陵究。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖奥帘,靈堂內(nèi)的尸體忽然破棺而出畔乙,到底是詐尸還是另有隱情,我是刑警寧澤翩概,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布牲距,位于F島的核電站,受9級(jí)特大地震影響钥庇,放射性物質(zhì)發(fā)生泄漏牍鞠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一评姨、第九天 我趴在偏房一處隱蔽的房頂上張望难述。 院中可真熱鬧,春花似錦吐句、人聲如沸胁后。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)攀芯。三九已至,卻和暖如春文虏,著一層夾襖步出監(jiān)牢的瞬間侣诺,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工氧秘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留年鸳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓丸相,卻偏偏與公主長(zhǎng)得像搔确,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子灭忠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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

  • 轉(zhuǎn)載:http://www.cocoachina.com/ios/20150601/11970.html RunL...
    Gatling閱讀 1,438評(píng)論 0 13
  • RunLoop的概念 一般來(lái)講膳算,一個(gè)線程一次只能執(zhí)行一個(gè)任務(wù),執(zhí)行完成后線程就會(huì)退出更舞。如果我們需要一個(gè)機(jī)制畦幢,讓線程...
    IOS學(xué)渣閱讀 461評(píng)論 1 4
  • http://www.cocoachina.com/ios/20150601/11970.html RunLoop...
    紫色冰雨閱讀 837評(píng)論 0 3
  • 原文地址:http://blog.ibireme.com/2015/05/18/runloop/ RunLoop ...
    大餅炒雞蛋閱讀 1,158評(píng)論 0 6
  • ——阿基米德說(shuō),給我一個(gè)支點(diǎn) 我可以撬動(dòng)地球” 在一個(gè)暖暖的午后的陽(yáng)臺(tái)上 不需要太多的語(yǔ)言 一杯玫瑰花...
    gezhe1967閱讀 161評(píng)論 0 3