首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iOS 5 NSURLConnection和NSOperationQueue -提供用户界面反馈

iOS 5 NSURLConnection和NSOperationQueue -提供用户界面反馈
EN

Stack Overflow用户
提问于 2012-03-11 17:38:46
回答 1查看 2.9K关注 0票数 2

我需要为JSON服务制作多个NSURLConnections。我希望每个WS调用都能在UI中保持信息,可能会有一个UIActivityIndicatorView和标签。到目前为止,我已经创建了一个NSURLConnection助手类来处理连接,并将URL委托放在视图中。这对于使用单个WS调用更新UI非常有用。

对于多个电话,我尝试使用一个NSOperationQueue。我想对队列中的一个操作进行setMaxConcurrentOperationCount,以便每个操作一次执行一个。以下是上的相关代码:

ViewController.m

代码语言:javascript
复制
#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

代码语言:javascript
复制
  @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?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-03-11 17:47:50

如果在添加操作之前将setSuspended设置为YES,则操作将被排队到挂起的队列中。我建议不要将队列挂起

而且,你的手术永远不会结束。您需要将操作本身指定为委托,并实现所有必要的委托方法。在这些方法中,您可以将消息转发到parentDelegate,并决定何时完成,并在适当时调用done方法(我建议使用connection:didFailWithError:connectionDidFinishLoading:)

这里有一个很好的教程:http://blog.9mmedia.com/?p=549

您还没有完全实现键值编码编译器属性的正确性。每当您调用willChangeValueForKey:时,还需要随后调用didChangeValueForKey

代码语言:javascript
复制
- (void)start
{
    ...
    [self willChangeValueForKey:@"isExecuting"];
    executing = YES;
    [self didChangeValueForKey:@"isExecuting"];

    [self main];
}

以及:

代码语言:javascript
复制
- (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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9657228

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档