我需要製作多個NSURLConnections到JSON Web服務。我希望每個WS調用都保持UI通知,可能帶有UIActivityIndicatorView和標籤。到目前爲止,我創建了一個NSURLConnection helper類來處理連接,並將URL委託放入View中。這對於通過單個WS調用來更新UI非常有用。iOS 5與NSOperationQueue的NSURLConnection - 提供UI反饋
對於多個調用,我試圖使用一個NSOperationQueue。我想將MaxConcurrentOperationCount設置爲隊列中的一個,以便每次操作一次執行一個操作。這裏有我的視圖控制器相關代碼:
ViewController.m
#import "URLOperationHelper.h"
@implementation ViewController
- (IBAction)showPopup:(id)sender
{
// Dictonary holds POST values
NSMutableDictionary *reqDic = [NSMutableDictionary dictionary];
// Populate POST key/value pairs
[reqDic setObject:@"pw" forKey:@"Password"];
[reqDic setObject:@"ur" forKey:@"UserName"];
operationQueue = [[NSOperationQueue alloc] init];
[operationQueue setMaxConcurrentOperationCount:1];
[operationQueue cancelAllOperations];
[operationQueue setSuspended:YES];
URLOperationHelper *wsCall1 = [[URLOperationHelper alloc] initWithURL:@"urlString1" postParameters:reqDic urlDelegate:self];
URLOperationHelper *wsCall2 = [[URLOperationHelper alloc] initWithURL:@"urlString2" postParameters:reqDic urlDelegate:self];
[operationQueue addOperation:wsCall1];
[operationQueue addOperation:wsCall2];
}
// Did the URL Connection receive a response
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(@"Did receive response: %@", response);
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
int code = [httpResponse statusCode];
// Handle status code here
webData = [[NSMutableData alloc]init];
}
// Did the URL Connection receive data
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(@"Did receive data: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
assert(webData != nil);
[webData appendData:data];
}
// Did the connection fail with an error?
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"%@", error);
}
// Executes after a successful connection and data download
-(void) connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"Connection finished");
}
@end
這裏是我的URLOperationHelper.m
@implementation URLHelper
- (id)initWithURL:(NSString *)urlPath
postParameters:(NSMutableDictionary *)postParameters
urlParentDelegate:(id) pDelegate
{
if(self = [super init])
{
connectionURL = urlPath;
postParams = postParameters;
parentDelegate = pDelegate;
}
return self;
}
- (void)done
{
// Cancel the connection if present
if(urlConnection)
{
[urlConnection cancel];
urlConnection = nil;
}
// Alert
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
executing = NO;
finished = YES;
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
}
- (void)cancel
{
// Possibly add an NSError Property
[self done];
}
- (void)start
{
// Make sure this operation starts on the main thread
if(![NSThread isMainThread])
{
[self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO];
return;
}
// Make sure that the operation executes
if(finished || [self isCancelled])
{
[self done];
return;
}
[self willChangeValueForKey:@"isExecuting"];
executing = YES;
[self main];
[self willChangeValueForKey:@"isExecuting"];
}
- (void)main
{
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:postParams options:NSJSONWritingPrettyPrinted error:&error];
// Convert dictionary to JSON
NSString *requestJSON = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@"JSONRequest: %@", requestJSON);
// Declare Webservice URL, request, and return data
url = [[NSURL alloc] initWithString:connectionURL];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
NSData *requestData = [NSData dataWithBytes:[requestJSON UTF8String] length:[requestJSON length]];
// Build the request
[request setHTTPMethod:@"POST"];
[request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:requestData];
// Connect to Webservice
// Responses are handled in the delegates below
urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:parentDelegate startImmediately:YES];
}
- (BOOL)isConcurrent
{
return YES;
}
- (BOOL)isExecuting
{
return executing;
}
-(BOOL)isFinished
{
return finished;
}
@end
說我遇到的問題是在從不調用URLOperation的啓動方法。 OperationQueue被創建並且操作被調用,但是在那之後,執行或者線程明智之後什麼也沒有發生。
此外,這是一個正確的思路,用這種NSOperationQueues提供UI反饋? I.E.從Operation中調用NSURLDelegates?
我註釋掉線和第一操作執行。但是,第二個操作從未開始。任何想法爲什麼? – Joshua 2012-03-11 18:24:19
編輯。你需要改變你的操作方式 – 2012-03-11 19:53:41
好吧,我通過向連接添加了[self done]來完成更新:didFailWithError和connectionDidFinishLoading :.這是一些很好的反饋。不過,我只能將第一個操作添加到隊列中執行。是因爲我有[operationQueue setMaxConcurrentOperationCount:1];? – Joshua 2012-03-11 20:59:42