【问题标题】:How to assign NSData from within NSOperationQueue to NSData from outside the NSOperationQueue如何将 NSOperationQueue 内部的 NSData 分配给 NSOperationQueue 外部的 NSData
【发布时间】:2013-10-18 19:07:25
【问题描述】:

我需要从 JSON 下载数据,并将数据分配给 NSOperationQueue 之外的 NSData。这是我的代码:

-(void)parsingInfo {
    NSURL *url = [NSURL URLWithString:@"http://someJSON.json"];
    NSData *data;

    [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:url] queue:downloadQueue completionHandler:^(NSURLResponse* response, NSData* jsonData, NSError* error){

        if(error)
        {
            // Error Downloading data
            NSLog(@"Error");
        }
        else
        {
            data = jsonData;
        }
    }];

    if (data) {
        NSError *error;
        NSDictionary *JSONDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];

        application = [JSONDic objectForKey:@"Applications"];
        NSArray *featured = [JSONDic objectForKey:@"Featured"];
        NSDictionary *dict2;
        dict2 = [featured objectAtIndex:0];

    } else {

        NSLog(@"Error, no data!");
    }
}

【问题讨论】:

  • 将代码的if(data) 部分移动到 NSOperation 队列中。基本上,您的函数将触发一个新线程来运行下载,然后将立即继续检查数据是否存在(可能在下载开始之前)。
  • 好的,但是数组应用程序将为零
  • 好的,那么当异步请求完成时,使用一个知道数组application 是什么的新函数进入主线程。

标签: ios json xcode nsoperationqueue


【解决方案1】:

将一个块传递给您的 NSOperation,该操作可以使用 NSData 对象作为参数调用该块。

【讨论】:

  • 你的意思是__block NSData *data吗?
  • 不,只有在要修改块中的数据时才需要它。您只希望操作将数据传递回块。
【解决方案2】:

如果您想在到达 'if (data)' 语句之前等待 'data' 被填充,那么要么.. a) 进行同步请求调用。

  + (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error

或者,

b) 用户信号量阻塞/中断此线程,直到您收到数据。

-(void)parsingInfo
{
            NSURL *url = [NSURL URLWithString:@http://someJSON.json];
            __block NSData *data;

                // Create a semaphore to block this thread ( or run loop) until we get response back from server.
            dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0);

            [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:url] queue:downloadQueue completionHandler:^(NSURLResponse* response, NSData* jsonData, NSError* error){

                if(error)
                {
                    // Error Downloading data
                    NSLog(@"Error");
                }
                else
                {
                    data = jsonData;
                }

               // Signal to release the semaphore (i.e. unblock the current thread).
                dispatch_semaphore_signal(waitSemaphore);

            }];
                // A dispatch semaphore is an efficient implementation of a traditional counting semaphore. Dispatch semaphores call down
            // to the kernel only when the calling thread needs to be blocked. If the calling semaphore does not need to block, no kernel call is made.
            while (dispatch_semaphore_wait(waitSemaphore, DISPATCH_TIME_NOW))
            {
                [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
            }

            // Release the semaphore.
            dispatch_release(waitSemaphore);

            if (data) {
                NSError *error;
                NSDictionary *JSONDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];

                application = [JSONDic objectForKey:@"Applications"];
                NSArray *featured = [JSONDic objectForKey:@"Featured"];
                NSDictionary *dict2;
                dict2 = [featured objectAtIndex:0];

            } else {

                NSLog(@"Error, no data!");
            }

}

请随时提出任何问题。

【讨论】:

  • 谢谢,现在超级快,但是你应该替换 NSData *data; with __block NSData *data;
  • 为什么要投反对票?这是一个公认的答案,我在我的一个项目中使用了这个解决方案。
  • 不要在 iOS 中使用同步网络/阻塞线程。没有必要,这是一个糟糕的设计。您可以使用块或委托以更加 cpu/UI 友好的方式完成所有操作。更不用说更简单了。
  • @jsd - 我同意您声明的意图:- 不阻塞 UI(主线程)。但是,如果您已经在另一个线程上发出数据提取请求(例如,用于某些数据提取目的),那么根据您当前线程的设计/目的,信号量方法是合适的。最初的问题没有提到“主”线程,所以我的回答/建议对用户面临的问题有效。希望我说服了你:)
  • 好的,我现在测试了一下,没那么快,有没有其他方法?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-04
  • 2013-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-23
  • 1970-01-01
相关资源
最近更新 更多