使用非同步呼叫的好處是,不需要等到函式結束返回,即可執行接下來的函式。如此從網路下載較大容量的資料,就不會讓使用者界面卡住。下載過程中的事件可請delegate處理。
在.h中宣告好IB需使用到的變數和代理:
@interface HTImageViewController : UIViewController <NSURLConnectionDataDelegate> @property (nonatomic, retain) NSMutableData *data; @property (nonatomic, retain) IBOutlet UIImageView *imageView; @property (nonatomic, retain) IBOutlet UILabel *label; @end
在.m中實作對應事件的處理:
- (void)viewDidLoad { [super viewDidLoad]; self.navigationController.navigationBarHidden = YES; [self beginDownload]; } -(void)beginDownload { NSURL *url = [NSURL URLWithString:@"https://cg2010studio.files.wordpress.com/2011/11/happymans-name-card-qr-code-qq-20130304s.jpg"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; if (connection) { self.data = [NSMutableData data]; } else { UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"連線失敗" message:@"無法建立連線" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alertView show]; } } #pragma mark - NSURLConnectionDataDelegate -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { self.label.text = @"接收到回應"; [self.data setLength:0]; } -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { self.label.text = @"下載中"; [self.data appendData:data]; } -(void)connectionDidFinishLoading:(NSURLConnection *)connection { self.label.text = @"下載完成"; UIImage *image = [UIImage imageWithData:self.data]; [self.imageView setImage:image]; } -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"連線失敗" message:@"無法順利完成連線" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [av show]; }
- 在http連線得到回應時,代理物件的connection:didReceiveResponse:會被呼叫。
- 之後不斷接收到http的資料時,代理物件的connection:didReceiveData:會被呼叫。
- 完成接收時,代理物件的connectionDidFinishLoading:會被呼叫。
- 如果沒有網路,就會出現警示,代理物件的connection:didFailWithError:會被呼叫。
接著使用同步呼叫與GCD的非同步執行,此時不需要用到delegate,主程式需要同步下載時,呼叫另一個執行緒來進行同步下載,當另一個執行緒下載完畢後,再呼叫主執行緒來進行畫面的更新。在下載的過程中,主執行緒因沒有被阻擋而能夠執行許多其它命令。
-(void)beginDownload { NSURL *url = [NSURL URLWithString:@"https://cg2010studio.files.wordpress.com/2011/11/happymans-name-card-qr-code-qq-20130304s.jpg"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; dispatch_queue_t downloadQueue = dispatch_queue_create("downloadQueue", DISPATCH_QUEUE_CONCURRENT); dispatch_async(downloadQueue, ^{ NSLog(@"開始下載"); NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; if (data) { NSLog(@"下載完成"); UIImage *image = [UIImage imageWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ [self.imageView setImage:image]; }); } else { NSLog(@"下載失敗"); dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"連線失敗" message:@"無法建立連線" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alertView show]; }); } }); }
參考:前進APP Store iOS 6 SDK 實戰演練。
隨意留個言吧:)~