Ios5 iOS 5 NSURLConnection与NSOperationQueue-提供用户界面反馈

Ios5 iOS 5 NSURLConnection与NSOperationQueue-提供用户界面反馈,ios5,nsurlconnection,nsoperationqueue,Ios5,Nsurlconnection,Nsoperationqueue,我需要与JSON Web服务建立多个NSURLConnection。我希望每个WS-call在UI中保持通知,可能带有UIActivityIndicatorView和标签。到目前为止,我已经创建了一个NSURLConnection助手类来处理连接,并将URL委托放置在视图中。这对于使用单个WS-call更新UI非常有用 对于多个调用,我尝试使用NSOperationQueue。我想在队列上将MaxConcurrentOperationCount设置为1,以便每个操作一次执行一个。以下是我的视图控

我需要与JSON Web服务建立多个NSURLConnection。我希望每个WS-call在UI中保持通知,可能带有UIActivityIndicatorView和标签。到目前为止,我已经创建了一个NSURLConnection助手类来处理连接,并将URL委托放置在视图中。这对于使用单个WS-call更新UI非常有用

对于多个调用,我尝试使用NSOperationQueue。我想在队列上将MaxConcurrentOperationCount设置为1,以便每个操作一次执行一个。以下是我的视图控制器上的相关代码:

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 
  @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
这是我的URLOperationHelper.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 
  @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
我遇到的问题是,从未调用url操作的Start方法。将创建OperationQueue并调用操作,但之后不会执行或线程方式发生任何操作


另外,这样使用NSOperationQueues提供UI反馈是否正确?也就是说,从操作调用NSURLDegories?

如果在添加操作之前将
setSuspended
设置为
YES
,则您的操作将排入暂停队列。。我建议不要在晚上暂停排队

此外,你的行动永远不会结束。您需要将操作本身指定为委托,并实现所有必要的委托方法。在这些方法中,您可以将消息转发给您的
parentDelegate
,并决定何时完成并在适当时调用您的done方法(我建议
连接:didFailWithError:
连接difinishload:

这里有一个很好的教程:

您还没有完全实现键值编码编译器属性的正确性。无论何时调用
willChangeValueForKey:
您还需要在之后调用
didChangeValueForKey

- (void)start
{
    ...
    [self willChangeValueForKey:@"isExecuting"];
    executing = YES;
    [self didChangeValueForKey:@"isExecuting"];

    [self main];
}
以及:


关于KVC,请参见此Q/A:

我注释掉了该行,并执行了第一个操作。但是,第二个操作从未启动。知道为什么吗?好的,我通过在连接中添加[self-done]进行了更新:didFailWithError和connectionDidFinishLoading:。这是一些很好的反馈。但是,我只能获得添加到队列中要执行的第一个操作。是因为我有[operationQueue setMaxConcurrentOperationCount:1];?