iOS學習系列 – 利用ASIHTTPRequest實現非同步隊列

來源:互聯網
上載者:User

      做過iOS開發應該都有見過ASIHTTPRequest這個強大的HTTP網路請求類庫,今天主要來介紹利用ASIHTTPRequest實現非同步隊列。

官方地址:http://allseeing-i.com/ASIHTTPRequest/

github地址:http://github.com/pokeb/asi-http-request/tree

      裡面具體可以進行HTTP常見的使用,Get,Post,同步,非同步方式進行請求,裡面內嵌一些請求方式,例如ASIWebPageRequest,即WebPage呈現方式;ASIS3Request,即Amazon Simple Storage Service (Amazon S3,http://aws.amazon.com/s3/);ASICloudFilesRequest,即Cloud Files CDN,(http://www.rackspace.com/),這些Request都是繼承基礎Request,ASIHTTPRequest,包括POST方式,ASPFormDataRequest,裡面還內建許可權驗證,SSL驗證以及緩衝請求的眾多功能,這些功能有興趣可以下載原始碼參考,今天我介紹它的一種Queue的機制,即通過將非同步請求放入隊列中,進行非同步呼叫,最終隊列完後產生一個Queue回調。

      目前,我有一個任務協同辦公的web項目,在用戶端方面,通過iOS請求Server上的工作清單,並且將工作清單Tasklist同步到了我的用戶端的本機資料庫中,在每一個工作清單中都有多個任務,相當於工作清單與任務是一對多的關係,由於我在手機端的操作,我將本地更新(修改、添加、刪除)的任務更新到本機資料庫中,至此我的每一條的工作清單可能都產生了一系列的任務的更新資料,這裡不妨這邊定義了一個changeLog的變化記錄類:

@interface ChangeLog : NSManagedObject

@property (nonatomic, retain) NSNumber * changeType;
@property (nonatomic, retain) NSString * taskId;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * value;

@end

這裡的taskId就是從server同步下來的任務Id或者本地建立的臨時Id,changeType就是更改的類型,例如它可以表示添加、修改、刪除等等,name表示實體的欄位名稱,例如”Subject”,”Body”等等,value就是對應”Subject”,”Body”的值了。

      現在,我想把這些任務的ChangeLog全部同步到Server端,必然在Server上需要相關的API作為支援。假如說,我現在的API的方法是

Sync(String tasklistId, String changes),相當說,我需要請求兩個參數,一個是TasklistId,另外一個在該TasklistId對應的Tasklist上將NSArray的ChangeLog集合,序列化一個JSON字串,這樣Server端擷取到資料就可以對changes進行還原序列化了。

編寫一個HttpWebRequest的類:

#import “ASIHTTPRequest.h”
#import “ASIFormDataRequest.h”
#import “ASINetworkQueue.h”
#import “Reachability.h”

@protocol HttpWebRequestDelegate <NSObject>

- (void)networkNotReachable;
- (void)requestFinished:(ASIHTTPRequest *)request;
- (void)requestFailed:(ASIHTTPRequest *)request;
- (void)addRequstToPool:(ASIHTTPRequest *)request;
- (void)queueFinished:(ASINetworkQueue *)queue;
- (void)notProcessReturned:(NSMutableDictionary*)context;

@end

@interface HttpWebRequest : NSObject

@property(nonatomic,assign) id<HttpWebRequestDelegate> delegate;

- (ASIFormDataRequest*)createPostRequest:(NSString*)url
params:(NSMutableDictionary*)params
headers:(NSMutableDictionary*)headers
context:(NSMutableDictionary*)context;

@end

createPostRequest的實現:

- (ASIFormDataRequest*)createPostRequest:(NSString*)url
params:(NSMutableDictionary*)params
headers:(NSMutableDictionary*)headers
context:(NSMutableDictionary*)context
{
Reachability *reachability = [Reachability reachabilityForInternetConnection];
[reachability startNotifier];
if (reachability.currentReachabilityStatus == NotReachable) {
return nil;
}
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:url]];
if (context)
{
[request setUserInfo:[NSDictionary dictionaryWithDictionary:context]];
}
if (headers)
{
for (NSString *key in headers.allKeys)
{
[request addRequestHeader:key value:[headers objectForKey:key]];
}
}
if(params)
{
for(NSString *key in params.allKeys)
{
[request setPostValue:[params objectForKey:key] forKey:key];
}
}
  
//cookies設定
NSHTTPCookieStorage *sharedHTTPCookie = [NSHTTPCookieStorage sharedHTTPCookieStorage];
//[request setUseCookiePersistence:YES];
[request setRequestCookies: [NSMutableArray arrayWithArray:sharedHTTPCookie.cookies]];
  
[request setTimeOutSeconds:SYSTEM_REQUEST_TIMEOUT];
[request setCachePolicy:ASIAskServerIfModifiedCachePolicy];
  
[request setValidatesSecureCertificate:NO];
return request;
}

這裡我用到一個ASIFormDataRequest的POST請求

再定義一個TaskService類:

- (void)syncTasks:(NSMutableArray*)tasklists
context:(NSMutableDictionary*)context
delegate id)delegate
{

}

這裡將本機資料庫的ChangeLog變動提交到服務端,假定tasklists已經是從本機資料庫取出來的待提交的資料

在開始實現之前,我們可能會這樣寫:

for (Tasklist *tasklist in tasklists)
{
//前面進行一些列的本機資料庫操作
NSMutableDictionary *data = [NSMutableDictionary dictionary];
[data setObject:tasklistId forKey:@”tasklistId”];
[data setObject:changeLogsJson forKey:@”changes”];

HttpWebRequest *request = [[HttpWebRequest alloc] init];
ASIFormDataRequest *postRequest = [request createPostRequest:url params:data headers:nil context:context1];

[request startAsynchronous];
}

startAsynchronous方法就進行一次非同步呼叫,並且通過

- (void)requestFinished:(ASIHTTPRequest *)request;

方法進行完成回調。

      但是,這樣就會產生一個問題,當你非同步請求一個sync_url的時候,這裡假如有10條的tasklist,就會產生10條的async,但是你該如何確保它10條都已經執行完畢呢,你也許會想到使用一個原子鎖,通過@property (atomic, retain) counter;來實現,但這裡,我使用了ASIHTTPRequest內建一個方式就是ASINetworkQueue隊列的方式來實現一個Queue的Finish的回調。

現在我重寫定義syncTasks的方法:

- (void)syncTasks:(NSMutableArray*)tasklists
context:(NSMutableDictionary*)context
queue:(ASINetworkQueue*)networkQueue
delegate id)delegate
{

}

這裡我多了一個ASINetworkQueue為類型的參數,現在我改寫syncTasks的實現:

networkQueue.delegate = delegate;
networkQueue.queueDidFinishSelector = @selector(queueFinished:);
networkQueue.requestDidFinishSelector = @selector(requestFinished:);
networkQueue.requestDidFailSelector = @selector(requestFailed:);

for (Tasklist *tasklist in tasklists)
{
//前面進行一些列的本機資料庫操作
NSMutableDictionary *data = [NSMutableDictionary dictionary];
[data setObject:tasklistId forKey:@”tasklistId”];
[data setObject:changeLogsJson forKey:@”changes”];

HttpWebRequest *request = [[HttpWebRequest alloc] init];
ASIFormDataRequest *postRequest = [request createPostRequest:url params:data headers:nil context:context1];

if(postRequest == nil) {
[delegate networkNotReachable];
break;
}
[networkQueue addOperation:postRequest];
[request release];
}

[networkQueue go];

      首先,對networkQueue進行一些初始化,例如加入委託,隊列完成回調,請求完成回調,錯誤回調等等,在forin語句中,將每條的postRequest請求加入到該非同步隊列中[networkQueue addOperation:postRequest];最後通過[networkQueue go];開始執行隊列中的非同步請求

這樣你就可以在所有request完成之後,即requestFinished回調完成之後,繼續執行queueFinished的回調。

這樣就實現了一個非同步請求的隊列。

最後調用的代碼入口:

NSMutableDictionary *context = [NSMutableDictionary dictionary];
[context setObject:@”SyncTasks” forKey:REQUEST_TYPE];
if(networkQueue)
{
[networkQueue reset];
}
networkQueue = [ASINetworkQueue queue];
[taskService syncTasks:tempTasklists context:context queue:networkQueue delegate:self];

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.