块、范围和设置变量 Objective C

Posted

技术标签:

【中文标题】块、范围和设置变量 Objective C【英文标题】:Blocks, scoping and setting variables Objective C 【发布时间】:2014-06-11 03:05:08 【问题描述】:

我正在使用 AFNetworking AFHTTPSessionManager 发出 GET 请求。当我记录响应对象时,会记录 responseObject。当我尝试记录我的 locationIDsDictionary 时,我得到空值。范围问题? locationIDsDictionary 需要是 _block 类型吗?

viewController.h
@property (strong, nonatomic) NSDictionary *locationIDsDictionary;

viewController.m
    [[LPAuthClient sharedClient]GET:getLocationIDString parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) 
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
        if (httpResponse.statusCode == 200) 
            dispatch_async(dispatch_get_main_queue(), ^

                _locationArray = responseObject[@"data"];
                NSLog(@"Response %@", responseObject);
            );
        

     failure:^(NSURLSessionDataTask *task, NSError *error) 
        NSLog(@"Failure %@", error);
    ];

    NSLog(@"locationIDsDictionary %@", _locationIDsDictionary);

编辑:输出

 Response 
data =     (
            
        id = 45388148;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = "TESTING HATE VENUE";
    ,
            
        id = 208947000;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = "The Greatest Isreal";
    ,
            
        id = 86128772;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = "Pike street";
    ,
            
        id = 33208867;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = abcde;
    ,
            
        id = 104267842;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = "somewhere over south dakota";
    ,
            
        id = 232446516;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = wow;
    ,
            
        id = 107511313;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = "Yum Yum.com";
    ,
            
        id = 189736241;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = "wow;l";
    ,
            
        id = 246109339;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = Fused;
    ,
            
        id = 153279132;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = 333;
    ,
            
        id = 115790356;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = "Bar Karma";
    ,
            
        id = 50341151;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = popoopo;
    ,
            
        id = 121590347;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = 26;
    ,
            
        id = 75286586;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = wow;
    ,
            
        id = 72889805;
        latitude = "37.785834";
        longitude = "-122.406417";
        name = test;
    ,
            
        id = 284599098;
        latitude = "37.785834009";
        longitude = "-122.406416997";
        name = "Urban Safari";
    ,
            
        id = 89500038;
        latitude = "37.785835266";
        longitude = "-122.406417847";
        name = "Cali Home";
    ,
            
        id = 8736810;
        latitude = "37.785835266";
        longitude = "-122.406417847";
        name = "Test%20Test%20Test";
    ,
            
        id = 45031994;
        latitude = "37.78584";
        longitude = "-122.4064";
        name = japaneses;
    ,
            
        id = 35874897;
        latitude = "37.785806574";
        longitude = "-122.406477728";
        name = "Hotel Palomar Fifth Floor Restaurant";
    
);
meta =     
    code = 200;
;

【问题讨论】:

因为你没有给它赋值? 请出示_locationIDsDictionary的声明,请出示以“Response”开头的完整NSLog输出。 【参考方案1】:

以 CrimsonChris 的回答为基础,GET: parameters: success: 方法是异步的。在这段代码中:

[[LPAuthClient sharedClient] GET:getLocationIDString parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) 
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
    if (httpResponse.statusCode == 200) 
        dispatch_async(dispatch_get_main_queue(), ^
            _locationArray = responseObject[@"data"];
            NSLog(@"Response %@", responseObject);
        );
    
 failure:^(NSURLSessionDataTask *task, NSError *error) 
    NSLog(@"Failure %@", error);
];
NSLog(@"locationIDsDictionary %@", _locationIDsDictionary);

success 参数是你的完成块,所以:

^(NSURLSessionDataTask *task, id responseObject) 
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
    if (httpResponse.statusCode == 200) 
        dispatch_async(dispatch_get_main_queue(), ^
            _locationArray = responseObject[@"data"];
            NSLog(@"Response %@", responseObject);
        );
    
 failure:^(NSURLSessionDataTask *task, NSError *error) 
    NSLog(@"Failure %@", error);

仅在 ios 完成您的下载任务时调用,因此您的字典仅在下载任务完成时被分配。同时,剩余的代码行正在执行,因此异步的含义 - 在不同的线程上执行。如果它是同步的,代码将被暂停,直到该代码块完成,这很糟糕,您会看到它在 iOS 应用程序中被翻译成freezy UI。

所以在执行下载任务时仍会调用 NSLog(@"locationIDsDictionary %@", _locationIDsDictionary);,因此它将评估为 nil - 当然,除非您的网速疯狂 :)

【讨论】:

那么我应该在哪里设置 locationIDsDictionary? @noobsmcgoobs 你把它分配在正确的地方,你只是NSLog把它放在了错误的地方。在它被初始化之前你是NSLogging,所以如果你想在分配它之后检查它是否被正确初始化NSLog它在完成块中。【参考方案2】:

你写...

当我尝试记录我的 locationIDsDictionary 时,我得到了 null。

由于您没有分享此日志的位置,我将假设您正在做这样的事情......

[self runMyGetLocationMethodAsynchronously];
NSLog(@"%@", _locationIDsDictionary);

这不起作用,因为您在 异步 方法的 success 块中设置了 _locationIDsDictionary。在该块运行之前,不会设置您的字典。

【讨论】:

以上是关于块、范围和设置变量 Objective C的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C autoreleasepool 指令影响范围之外的变量。

循环播放页面时出错。返回对象变量或未设置块变量

从C语言的变量声明到Objective-C中的Block语法

检查变量是不是设置在全局范围内?

“无法重新声明块范围的变量”和“SyntaxError:意外的令牌'导出'”[关闭]

如何解决 Testcafe 和 Jest 之间的类型冲突? (“无法重新声明块范围变量'test'”)