我需要为JSON服务制作多个NSURLConnections。我希望每个WS调用都能在UI中保持信息,可能会有一个UIActivityIndicatorView和标签。到目前为止,我已经创建了一个NSURLConnection助手类来处理连接,并将URL委托放在视图中。这对于使用单个WS调用更新UI非常有用。
对于多个电话,我尝试使用一个NSOperationQueue。我想对队列中的一个操作进行setMaxConcurrentOperationCount,以便每个操作一次执行一个。以下是上的相关代码:
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的Start方法从未被调用过。创建了OperationQueue并调用了操作,但在此之后,执行或线程无关。
另外,这是使用NSOperationQueues提供UI反馈的正确思路吗?即从行动中打电话给NSURLDelegates?
发布于 2012-03-11 17:47:50
如果在添加操作之前将setSuspended设置为YES,则操作将被排队到挂起的队列中。我建议不要将队列挂起
而且,你的手术永远不会结束。您需要将操作本身指定为委托,并实现所有必要的委托方法。在这些方法中,您可以将消息转发到parentDelegate,并决定何时完成,并在适当时调用done方法(我建议使用connection:didFailWithError:和connectionDidFinishLoading:)
这里有一个很好的教程:http://blog.9mmedia.com/?p=549
您还没有完全实现键值编码编译器属性的正确性。每当您调用willChangeValueForKey:时,还需要随后调用didChangeValueForKey:
- (void)start
{
...
[self willChangeValueForKey:@"isExecuting"];
executing = YES;
[self didChangeValueForKey:@"isExecuting"];
[self main];
}以及:
- (void)done
{
...
// Alert
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
executing = NO;
finished = YES;
[self didChangeValueForKey:@"isFinished"];
[self didChangeValueForKey:@"isExecuting"];
}请参阅KVC:when to use "willChangeValueForKey" and "didChangeValueForKey"?的Q/A
https://stackoverflow.com/questions/9657228
复制相似问题