Just a Computer Graphics Studio & My Life

使用非同步呼叫的好處是,不需要等到函式結束返回,即可執行接下來的函式。如此從網路下載較大容量的資料,就不會讓使用者界面卡住。下載過程中的事件可請delegate處理。

NSURLConnction執行非同步呼叫

在.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:會被呼叫。

NSURLConnction執行非同步呼叫2

接著使用同步呼叫與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 實戰演練。

Advertisements

發表留言

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

標籤雲

%d 位部落客按了讚: