1. 程式人生 > >ios--關於子執行緒傳送網路請求接受不到響應問題

ios--關於子執行緒傳送網路請求接受不到響應問題

最近在學IOS開發,正試著寫個花瓣網圖片批量下載的APP,過程中遇到個問題:我起了一個子執行緒用來,通過不斷的發請求,接受響應來非同步下載圖片,從而可以邊下載,邊在主執行緒中執行其他操作。起初,是直接在主執行緒中除錯程式碼,圖片下載很順利,連結URL部分程式碼如下:

    NSURL *boardURL = [NSURL URLWithString:[boardURLString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    NSURLRequest *request = [NSURLRequest requestWithURL:boardURL];
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
 //   NSLog(@"%p--%p", [NSThread mainThread], [NSThread currentThread]);
    [conn start];
後來用NSThread新建了個子執行緒,把上面的程式碼放到子執行緒的方法呼叫。結果NSURLConnectionDataDelegate代理方法- (void)connection: didReceiveResponse: 等都沒有執行,即沒有收到響應。注意,並不是網路問題,同樣條件下在主執行緒中是OK的。自己思考了下,應該是伺服器返回響應了,但是沒能傳輸到子執行緒中去,猜想可能是子執行緒在執行完被呼叫的方法後沒能等待接受到響應就被自動釋放掉了,或者是在多執行緒下,返回的響應需要進行某種識別才能正確傳輸給對應的執行緒。感覺第一種猜想可能性較大,問了下度娘,發現可能和NSRunLoop有關,最終實踐證明第一種猜想是對的。程式碼中的解決如下
    NSURL *boardURL = [NSURL URLWithString:[boardURLString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    NSURLRequest *request = [NSURLRequest requestWithURL:boardURL];
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    NSLog(@"%p--%p", [NSThread mainThread], [NSThread currentThread]);
    [conn start];
#warning 這裡關於執行緒的使用點,可以研究下
    //表示當前執行緒一直接受輸入源,不會被釋放,如果沒有下面的程式碼,子執行緒到這裡就被釋放,不會接受其他輸入源,從而不會在子執行緒中執行NSURLconnectionDataDelegate方法
    while(_doingJob) {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
_doingJob是全域性變數,子執行緒完成所需的工作後設置為NO。

原來,子執行緒方法中執行完[conn start];後方法結束,隨即該執行緒就被釋放掉了,這樣即便伺服器返回了資料,也沒有接受源接受資料,當然代理的那些方法也不會執行。加上了下面那個while迴圈後,就能保證該子執行緒一直存在,直到完成所需的工作跳出迴圈為止。關於NSRunLoop的原理,我會整理出篇部落格放《IOS學習篇》分類裡。