objective-c - 对象-C : __block variable not retaining data

标签 objective-c asynchronous objective-c-blocks

我想我可能在这里遇到了异步问题,这让我很困扰,因为我以为我已经解决了它。不管怎样,我正在进行一堆网络服务调用,如下所示:

//get the client data
__block NSArray* arrClientPAs;
[dataManager getJSONData:strWebService withBlock:^(id results, NSError* error) {            
    if (error) {
        UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Getting Client Data Error!" message:error.description delegate:nil cancelButtonTitle:NSLocalizedString(@"Okay", nil) otherButtonTitles:nil, nil];
        [alert show];
    } else {
        arrClientPAs = results;
    }
 }];

而 getJSONData 就像这样:

- (void) getJSONData : (NSString*) strQuery withBlock:(void (^)(id, NSError *))completion {
    NSDictionary* dictNetworkStatus = [networkManager checkNetworkConnectivity];
    NetworkStatus networkStatus = [[dictNetworkStatus objectForKey:@"Status"] intValue];

    if (networkStatus != NotReachable) {
        //set up the url for webservice
        NSURL* url = [NSURL URLWithString:strQuery];
        NSMutableURLRequest* urlRequest = [NSMutableURLRequest requestWithURL:url];

        //set up the url connection
        __block id results;
        [NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue mainQueue] completionHandler:
         ^(NSURLResponse* response, NSData* jsonData, NSError* error) {
             if (error) {
                 completion(nil, error);
                 return;
             }

            results = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves | NSJSONReadingAllowFragments error:&error]; 
            completion(results, nil);
         }];            
    } else {
        //not connected to a network - data is going to have to come from coredata
    }
}

在第一个 block 中,如果我记录 arrClientData,我可以看到我期望的数据,但是当我在它之后记录 arrClientData 时,它为零。我正在关注这个线程 - How to return a BOOL with asynchronous request in a method? (Objective-C)和其他几个。

显然我正在尝试在异步调用后获取数据。任何帮助,将不胜感激。

最佳答案

我认为问题在于“异步”的含义。这是一个图表:

Step One
__block result;
Step Two - do something asynchonous, including e.g. setting result
Step Three

这里的事情发生的顺序是什么?第三步发生在第二步完成之前。 就是异步的含义:它的意思是,“继续执行这段代码,不要等待异步内容完成。”因此,在第三步发生时,result 变量尚未设置为任何内容。

所以,你只是用你的__block 结果误导了自己。 __block 或没有 __block,您将无法知道结果是什么之后,因为没有“之后”。您的代码在 __block 结果 设置之前就已完成。这就是为什么异步代码使用稍后运行的回调(例如您的完成 block ),因为它是异步代码的连续部分(附加到)。您可以通过回调将结果向下传递,但您无法在 block 内向上有效地设置它并期望稍后检索它。

所以,你的整体结构是这样的:

__block NSArray* arrClientPAs; // it's nil
[call getJSONdata] = step one
     [call sendAsynchronousRequest]
          do the block _asynchronously_ = step two, tries to set arrClientPAs somehow
step three! This happens _before_ step two, ...
... and this entire method ends and is torn down ...
... and arrClientPAs is still nil! 🌻

我再说一遍:你不能从异步 block 中传递任何信息。你只能往下走。您需要异步 block 调用某个独立持久对象的某些方法来将结果交给它并告诉它使用该结果(并且在主线程上小心执行,否则会造成严重破坏) 。您不能使用任何自动变量来实现此目的,例如您声明的 NSArray 变量arrClientPAs;不再有自 Action 用域,方法结束,自动变量消失,没有更多的代码可以运行。

关于objective-c - 对象-C : __block variable not retaining data,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21890637/

相关文章:

ios - 底部UITableView隐藏时如何让UIScrollView占据屏幕高度?

ios - 向 UITableView 添加字幕数组

javascript - 使用 async/await react 设置状态

android - GLES iOS、Android RenderBuffer 同步还是异步?

javascript - 获取请求会产生包含数据的响应,但是当专门访问 .data 时,它会产生未定义的结果

Objective-C++ block 与 Objective-C block

ios - 使用 block 在表中加载图像-dispatch_async返回值

ios - AutoLayout uitableviewcell in landscape and on iPad calculating height based on portrait iPhone

iOS 在 afnetworking 2.0 成功和失败 block 中设置属性时出现问题

objective-c - 在运行时打印 Objective-C 方法实现