IOS Learning Series-asynchronous queue using ASIHTTPRequest

Source: Internet
Author: User

I have been familiar with ASIHTTPRequest, a powerful HTTP network request class library for iOS development. Today I will introduce how to use ASIHTTPRequest to Implement Asynchronous queues.

Official Address: http://allseeing-i.com/ASIHTTPRequest/

Github address: http://github.com/pokeb/asi-http-request/tree

Specifically, HTTP requests can be implemented through Get, Post, synchronous, and asynchronous requests. Some request methods are embedded in the request, such as ASIWebPageRequest, that is, WebPage rendering; ASIS3Request, amazon Simple Storage Service (Amazon S3, http://aws.amazon.com/s3/); ASICloudFilesRequest, that is, Cloud Files CDN, (http://www.rackspace.com/), these requests are inherited from the basic Request, ASIHTTPRequest, including the post method, ASPFormDataRequest, it also has built-in permission verification, SSL verification, and many functions for caching requests. If you are interested in these functions, you can download the source code reference. Today I will introduce its Queue mechanism, that is, by placing asynchronous requests into the Queue for asynchronous calling, a Queue callback is generated after the Queue is complete.

Currently, I have a web project for collaborative work. On the client side, I request the task list on the Server through iOS and synchronize the task list Tasklist to the local database of my client, there are multiple tasks in each task list, which is equivalent to the one-to-many relationship between the task list and tasks. Due to my operations on the mobile phone, I update (modify, add, and delete) the tasks locally) the task is updated to the local database. So far, each of my task lists may generate a series of task update data. Here we may wish to define a changeLog Change Record class:

@ Interface ChangeLog: NSManagedObject

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

@ End

Here, the taskId is the task Id synchronized from the server or the temporary Id created locally. changeType is the type of change, for example, it can indicate adding, modifying, and deleting, name indicates the field name of the object, such as "Subject" and "Body". value indicates the value corresponding to "Subject" and "Body.

Now, if I want to synchronize all the ChangeLog of these tasks to the Server, related APIs must be used as support on the Server. Assume that my current API method is

Sync (String tasklistId, String changes). In other words, I need to request two parameters: TasklistId and ChangeLog set of NSArray ON THE Tasklist corresponding to the TasklistId, serialize a json string so that the Server can deserialize changes after obtaining data.

Compile an HttpWebRequest class:

# 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

Implementation of 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;
}

Here I use a POST request of ASIFormDataRequest

Define another TaskService class:

-(Void) syncTasks :( NSMutableArray *) tasklists
Context :( NSMutableDictionary *) context
Delegate id) delegate
{
...
}

Here, the ChangeLog change of the local database is submitted to the server, assuming that tasklists is the data to be submitted from the local database.

Before implementation, we may write as follows:

For (Tasklist * tasklist in tasklists)
{
// Perform operations on the local database of some columns
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];
}

The startAsynchronous method performs an asynchronous call and uses

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

Method to complete the callback.

However, this will cause a problem. When you asynchronously request a sync_url, if there are 10 tasklists, 10 async will be generated, but how do you ensure that all 10 of them have been executed? You may think of using an atomic lock through @ property (atomic, retain) counter;, but here, I used ASIHTTPRequest to implement the Completion callback of a Queue in ASINetworkQueue Queue mode.

Now I want to override the syncTasks method:

-(Void) syncTasks :( NSMutableArray *) tasklists
Context :( NSMutableDictionary *) context
Queue :( ASINetworkQueue *) networkQueue
Delegate id) delegate
{
...
}

Here I have a parameter of the ASINetworkQueue type, and now I want to rewrite the implementation of syncTasks:

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

For (Tasklist * tasklist in tasklists)
{
// Perform operations on the local database of some columns
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];

First, initialize the networkQueue, such as adding a delegate, queue completion callback, request Completion callback, and error callback. In the forin statement, add each postRequest request to the asynchronous queue [networkQueue addOperation: postRequest]. Then, use [networkQueue go] To start executing asynchronous requests in the queue.

In this way, after all the requests are completed, that is, after the requestFinished callback is complete, you can continue to execute the queueFinished callback.

In this way, an asynchronous request queue is implemented.

The code entry for the last call:

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];

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.