如何使用相同的方法将NSURLSession的结果分配给变量? [英] How to assign result of NSURLSession to a variable in same method?

查看:121
本文介绍了如何使用相同的方法将NSURLSession的结果分配给变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要说我是Objective-C的新手,那就太轻描淡写了.我主要是Ruby/Rails开发人员,当涉及到OOP& amp;时,它完全宠坏了我.一般编程.

To say I'm new to Objective-C would be a huge understatement. I'm primarily a Ruby/Rails developer and it completely spoiled me when it comes to OOP & programming in general.

在厌倦了阅读教程之后,我决定尝试使用NSRULSession击中我的Rails应用程序之一(《上古卷轴在线》技能规划师),在我的iOS应用上显示一些JSON响应.代表没有任何意义,我不确定如何将此功能分解为方法等,因此我认为我将使其保持简单和简单.在viewDidLoad()方法中完成所有操作(是的,我知道这是不好的做法).

After getting tired of reading tutorials, I decided to try to use NSRULSession to hit one of my Rails apps (an Elder Scrolls Online skill planner) & display some of the JSON response on my iOS app. Delegates make no sense, I'm not sure how to break this functionality up into methods, etc, so I thought I'd keep it simple & do it all in the viewDidLoad() method (yes, I know it's bad practice).

- (void)viewDidLoad {
    [super viewDidLoad];

    __block NSDictionary *skillData; // No clue what __block is

    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"http://www.esomix.com/skill_builds/17.json"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        NSLog(@"%@", json[@"name"]);
        skillData = json;
    }];

    [dataTask resume];

    UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 200, 100)];
    myLabel.textColor = [UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1];
    [self.view addSubview:myLabel];

    NSLog(@"%@", skillData[@"name"]);
    NSLog(@"bottom of method");
}

经过大量的摸索,我发现尽管在底部的NSLogs之前有NSURLSession代码,但在渲染它们后它会返回其数据.难怪我的label.text(未显示)没有设置好!这是我的三个NSLog的顺序:

After lots of toying around, I figured out that despite the NSURLSession code before my NSLogs at the bottom, it returns its data after they're rendered. No wonder my label.text (not shown) wasn't getting set! Here's the order of my three NSLogs:

(null)
bottom of method
Single-Target Lockdown Sniper

我想我的问题是,最简单,正确的方法是发出JSON API请求并在数据返回后使用数据生成UI元素/其他任务.非常感谢!

I guess my question is what's the simplest, proper way to make an JSON API request and use the data to generate a UI element/other tasks after the data has returned. Thanks so much!

推荐答案

几个澄清点:

  1. 您问

  1. You ask

最简单,正确的方法是发出JSON API请求并在数据返回后使用数据生成UI元素/其他任务

what's the simplest, proper way to make an JSON API request and use the data to generate a UI element/other tasks after the data has returned

简而言之,请在完成代码块内而不是在完成代码块内使用JSON响应,例如:

In short, use the JSON response inside the completion block, not after it, for example:

- (void)viewDidLoad 
{
    [super viewDidLoad];

    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"http://www.esomix.com/skill_builds/17.json"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        NSDictionary *skillData = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

        // use `skillData` here

        // finally, any UI/model updates should happen on main queue

        dispatch_async(dispatch_get_main_queue(), ^{
            UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 200, 100)];
            myLabel.textColor = [UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1];
            myLabel.text = skillData[@"name"]; // or whatever you wanted from `skillData`
            [self.view addSubview:myLabel];
        });
    }];

    [dataTask resume];

    // don't try to use `skillData` here, as the above block runs asynchronously,
    // and thus `skillData` will not have been set yet
}

  • __block限定符的目的是让块更新其作用域在块之外的变量.但是,由于NSURLSessionDataTask是异步运行的,因此没有必要尝试在该块之外引用skillData(因为viewDidLoad方法将在调用NSURLSessionDataTaskcompletionHandler之前就已经完成了,如图所示)您的NSLog结果).

  • The purpose of the __block qualifier is to let the block update a variable whose scope is outside the block. But, because the NSURLSessionDataTask runs asynchronously, there's no point in trying to reference skillData outside that block (because the viewDidLoad method will have completed well before the completionHandler for the NSURLSessionDataTask is invoked, as illustrated by your NSLog results).

    因此,由于在块外引用skillData没有意义,因此在块外使用__block限定符定义它也没有意义.只需使其成为块内的局部变量即可.如果要更新模型(或可能更新视图控制器的某些属性),则可以这样做(但是在处理类属性和ivars时,不需要__block限定符).

    So, since there's no point in referencing skillData outside the block, then there's no point in defining it with the __block qualifier outside of the block. Just make it a local variable inside the block. If you want to update your model (or perhaps some properties of the view controller), you can do that (but when dealing with class properties and ivars, no __block qualifier is needed).

    这篇关于如何使用相同的方法将NSURLSession的结果分配给变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆