之前偷懶,讀取網頁資料時,我直接用 NSData 或 NSString 的 initWithContentsOfURL 的方法。雖然一行程式碼 程式碼就解決了,但缺點就是整個程式就停在那裡,非得等到網頁資料都下載完了後,才能繼續執行程式。
在預設的情況下,一個 iPhone App 只有一條執行緒(Thread),簡單的說就是同一時間只能做一件事,所以當你用 NSData 或 NSString 的 initWithContentsOfURL 的方法來載入網頁資料時,整個程式就會停在那裡,直到網頁資料都下載完了後,才會繼續執行下一行的程式碼。繼然程式停在那不動,當然你不論怎麼加上其它的動畫或View都不會有作用,這就是我昨天一直失敗的原因。
所以有兩種方式來解決這個問題,一是自己開 Thread 來用時做好幾件事,二是使用委託處理的方式,把要做的事情委託出去,等事情做完後,被委託的人會通知你事情已經處理完了。這也就是 iOS 一直強調的 delgate model。
自己開 Thread 並不適合用在 iT邦幫忙 App 裡,因為我必需要知道網頁資料何時會下載完畢,等下載完畢後,再把載入等待畫面給移除。所以我需要找到一個能幫我下載網頁資料,然後下載完後能通知我的一個類別,那個就是 - NSURLConnection。
NSURLConnection 宣告使用的程式碼如下:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://ithelp.ithome.com.tw/?tab=share"]];
[NSURLConnection connectionWithRequest:request delegate:self];
它需要兩個參數,一個是 NSURLRequest 物件,另一個是 delegate 物件。上面的程式碼把 delegate 指向自己(self),也就是目前所在的類別來接受 NSURLConnect 的事件。最重要的有四個事件處理的方法:
//是否收到網站的回應
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[htmlData setLength:0];
}
//收到網站傳回的資料
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[htmlData appendData:data];
}
//網頁資料下載完畢
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"Succeeded! Received %d bytes of data",[htmlData length]);
NSLog(@"%@", [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding]);
}
//網路連線錯誤
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[connection release];
NSLog(@"Connection failed! Error - %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
htmlData 是個 NSMutableData 的物件,當 NSURLConnect 連上網站時,我先把 htmlData 清空準備來接收網頁資料。NSURLConnection 會把網頁資料一段一段下載回來,每當下載一部份時,didReceiveData 方法會收到通知,這時我把資頁資料給存放進 htmlData 物件裡。等到全部下載回來後,會呼叫 connectionDidFinishLoading 方法,這時我就把網頁的資料給印出來...
當下載的過程中發生錯誤時,會呼叫 didFailWithError 的方法,這時我會印出錯誤訊息,看看發生了什麼事。
用了 NSURLConnection 之後,我就可以叫它去下載網頁資料,程式讓載入等待畫面顯示出來,網頁資料下載完畢後,再把載入等待畫面移除,最後顯示文章列表。
程式碼我還需要整理一下,讓讀取文章內容時,也一樣使用 NSURLConnection,預計明天開放 0.3 版的程式碼讓大家下載。