说我是Objective-C的新手将是一个巨大的轻描淡写。我主要是一个Ruby / Rails开发人员,当谈到OOP& amp;编程一般。
在厌倦了阅读教程之后,我决定尝试使用NSRULSession来点击我的一个Rails应用程序(Elder Scrolls Online技能规划师)&在我的iOS应用程序上显示一些JSON响应。代表没有任何意义,我不知道如何将这个功能分解为方法等,所以我认为我会保持简单&在viewDidLoad()方法中完成所有操作(是的,我知道这是不好的做法)。
- (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的顺序:
(null)
bottom of method
Single-Target Lockdown Sniper
我想我的问题是,在返回数据后,制作JSON API请求并使用数据生成UI元素/其他任务的最简单,正确的方法是什么。非常感谢!
答案 0 :(得分:3)
一些澄清要点:
你问
在数据返回后,制作JSON API请求并使用数据生成UI元素/其他任务的最简单,正确的方法是什么
简而言之,在完成块内使用JSON响应,而不是在它之后,例如:
- (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
方法将在completionHandler
之前完成{如NSURLSessionDataTask
结果所示,{1}}会被调用。
因此,由于在块之外引用NSLog
没有意义,因此使用块外的skillData
限定符来定义它是没有意义的。只需将其作为块内的局部变量即可。如果要更新模型(或者可能是视图控制器的某些属性),可以这样做(但在处理类属性和ivars时,不需要__block
限定符。)