ASIHTTPRequest 筆記

来源:互联网 发布:疯狂联盟座狼升星数据 编辑:程序博客网 时间:2024/06/06 15:40

ASIHTTPRequest 是 Objective-C 上知名的專門用來處理 HTTP requests 的框架,不過,作者似乎已經停止更新了(但是在 iOS 5 還是運作得很正常)。前陣子發現另一個 network framework 叫 AFNetworking,似乎挺不錯的,有空再去試試,雖然我最近寫 mobile app 已經寫到有點煩了…… AFNetworking 是 Gowalla 團隊開發的,對,就是那個被 Facebook 收購然後淒慘地關站的 Gowalla。

Add To Your Xcode Project

詳見:Using ASIHTTPRequest in an iOS project。

直接在 Finder 中把 ASIHTTPRequest 的檔案包含目錄拉進 xcode 裡,然後選擇 “Create groups for any added folders”,目錄的結構會像這樣:

ASINetworkQueue

我通常會在每個 view controller 裡面放一個 ASINetworkQueue 物件,由它來統一處理這個頁面的所有 requests。

12345678910111213141516171819202122232425262728293031
- (void)viewDidLoad{    [super viewDidLoad];    requestQueue = [[ASINetworkQueue alloc] init];    // count = 1,就算是非同步,也會是序列執行    requestQueue.maxConcurrentOperationCount = 15;    // ASIHTTPRequest 默認的情況下,queue 中只要有一個 request fail 了,整個 queue 裡的所有 requests 也都會被 cancel 掉    [requestQueue setShouldCancelAllRequestsOnFailure:NO];    // go 只需要執行一次    [requestQueue go];}- (void)viewWillDisappear:(BOOL)animated{    [super viewWillDisappear:animated];    // 離開這個頁面就暫停所有的 requests,之後又回到這個頁面時,可以繼續未完成的請求    [self.requestQueue setSuspended:YES];}- (void)viewWillAppear:(BOOL)animated{    [super viewWillAppear:animated];    // 恢復執行 requests    [self.requestQueue setSuspended:NO];}

Asynchronous Request(非同步請求)

基本上你應該不會想在 mobile 上使用同步請求,因為它會整個拖住畫面的渲染,也不能響應用戶的操作,所以通常的用法是:

123456789101112131415161718192021222324252627282930313233343536
- (void)followMember{    NSURL *url = [NSURL URLWithString:@"http://example.com/member/follow"];    /*     帶 POST / GET query 參數的請求要用 ASIFormDataRequest     下載圖片之類的單純的請求就用 ASIHTTPRequest     */    ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];    /*     通常會把 delegate 指定為當前的 view controller     你把 callback selector 寫在哪裡,delegate 就是哪個     */    [request setDelegate:self];    [request setDidFinishSelector:@selector(didFollowMember:)];    [request setDidFailSelector:@selector(didServerFail:)];    // POST Query    [request setPostValue:@"1234" forKey:@"user_id"];    [request setPostValue:@"5678" forKey:@"target_id"];    [request setPostValue:@"member" forKey:@"follow_type"];    // 放進 queue 的 request 就是非同步,不需要再特地 [request startAsynchronous] 了    [requestQueue addOperation:request];}- (void)didFollowMember:(ASIHTTPRequest *)request{    NSLog("request 得到 HTTP 200 的 response 之後,就會執行這個 callback");}- (void)didServerFail:(ASIHTTPRequest *)request{    NSLog("server 掛掉、request timeout 或 request 被強制 cancel 掉之後,就會執行這個 callback");}

callback selector 一定會在 main thread 執行,在 iOS 中,如果要進行 UI 操作(例如 [self.tableView reloadData] 之類的),必須是在 main thread。

延伸閱讀:

  • ASIHTTPRequest example code
  • ASIHTTPRequest 中文文档

Download Image

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
- (void)downloadImage:(NSMutableDictionary *)photoInfo{    NSURL *photoURL = [NSURL URLWithString:@"http://example.com/images/1234.jpg"];    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:photoURL];    [request setDelegate:self];    // cache    [request setDownloadCache:[ASIDownloadCache sharedCache]];    [request setCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];    [request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];    // [request setSecondsToCache:60 * 60 * 24 * 30]; // cache 30 天    // time out 自動重試的次數    [request setNumberOfTimesToRetryOnTimeout:2];    // callbacks    [request setDidFinishSelector:@selector(didDownloadImage:)];    [request setDidFailSelector:@selector(didServerFail:)];    [request setDidReceiveResponseHeadersSelector:@selector(dummySelector)];    [request setDidStartSelector:@selector(dummySelector:)];    /*     userInfo 的資料會被帶去 callback methods     而且 request.userInfo 會 retain 它          在這個例子中     一個頁面可能有很多個 UIImageView     你可以把對應的 UIImageView 放進 userInfo     這樣 callback 才知道要把下載下來的圖片放到哪一個 UIImageView     */    request.userInfo = photoInfo;    [self.requestQueue addOperation:request];}- (void)didDownloadImage:(ASIHTTPRequest *)request{    NSData *imageData = [request responseData];    UIImage *image = [[UIImage alloc] initWithData:imageData];    UIImageView *imageView = [request.userInfo objectForKey:@"imageView"];    if (imageView.subviews.count > 0) {        [imageView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];    }    [imageView setImage:image];    [image release];}/* 我發現如果沒有指定 setDidReceiveResponseHeadersSelector 和 setDidStartSelector 常常就會發生不明的 crash 所以我就不求甚解地加了這一行  但是老實說我完全不知道為什麼 不過事情都搞到這個地步了 其實我也不是那麼想知道原因 我只想準時下班啊~~~ */- (void)dummySelector:(ASIHTTPRequest *)request{    // do nothing}

延伸閱讀:

  • ASIHTTPRequest - 使用 download cache
  • 让 ASIHTTPRequest 不占用主线程 - keakon 的涂鸦馆

Release

在你的 view controller 的 dealloc 這樣寫:

1234567891011
- (void)dealloc{    for (ASIHTTPRequest *request in requestQueue.operations) {        /*         因為 ASIHTTPRequest 並不會 retain 它的 delegate         這樣可以避免 delegate 被 release 之後         request callback 回來卻找不到東西執行而 crash        */        [request clearDelegatesAndCancel];    }}

因為 request 被 cancel 之後,會執行 didFailSelector 這個 callback,所以你應該設置 [request setDelegate:nil],這樣就不會執行 callback 了。而 [request clearDelegatesAndCancel] 其實就是 [request setDelegate:nil]; [request cancel];。

 Mar 12th, 2012  Objective-C, iOS, iOS-Library

原创粉丝点击