2015年1月22日 星期四

[Objective-C] 使用NSURLConnection - 來取得網站資料(sendAsynchronousRequest)

在此介紹另一種NSURLConnection取得網站資料的方法。

使用這個物件方法:

+ (void)sendAsynchronousRequest:(NSURLRequest*) request
                          queue:(NSOperationQueue*) queue

              completionHandler:(void (^)(NSURLResponse* response, NSData* data, NSError* connectionError)) handler NS_AVAILABLE(10_7, 5_0);

此方法是非同步下載,因此可以給使用者較好的體驗(不會卡住整個APP)

這個例子我們會從網站下載一個JSON文件,JSON文件的網址如下:

http://data.taipei.gov.tw/opendata/apply/json/RkRDNjk0QzUtNzdGRC00ODFCLUJBNDktNEJCMUVCMDc3ODFE

先宣告NSURL物件,並透過此NSURL來產生NSURLRequest物件:

NSURL *url = [NSURL URLWithString:kJSON];
NSURLRequest *request = [NSURLRequest requestWithURL:url];

因為這個例子會在另一個Queue(執行緒)裡面執行,因此在此宣告一個Queue
NSOperationQueue *queue = [NSOperationQueue new];

最後再使用NSURLConnection的類別方法來下載網站的資料

[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if([data length] > 0 && connectionError == nil){
//收到正確的資料,而且沒有連線錯誤

NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@" , dict);
        
//告知主執行序下載完成
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"資料下載" message:@"下載完成" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
            
[alert show];
            
});
}else if ([data length] == 0 && connectionError == nil){
//沒有資料,而且連線沒錯誤
}else if(connectionError != nil){
//連線有錯誤
}
}];

透過data的長度及connectionError的狀態來得知是否有錯誤發生,

此外如果成功的話,要使用
dispatch_async(dispatch_get_main_queue(), ^{}
來告知主執行緒已經下載完成了,因為UI之類的變化都是在主執行緒完成,

可以試著把dispatch_async(dispatch_get_main_queue(), ^{}註解掉,
會過很久才跳出UIAlertView的顯示,但是其實檔案很早就下載好了。

使用這種下載方式可以很輕鬆的下載各個不同的網址,但是你沒辦法像NSURLConnectionDataDelegate一樣可以掌握各個階段的狀態。