异步json请求Objective C

Asynchronous json request Objective C

我正在开发我的第一个 iPhone 应用程序,我正在调用一个 API 到 return 一些 JSON 来填充我的 [=22] 的不同元素=].目前我已经在我在 viewDidLoad 方法中调用的助手 class 中实现了一个同步方法。

-(NSDictionary*) dataRequest: (NSString*)url withMethod:(NSString*)method
{

NSError *e;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:url]];
[request setHTTPMethod:method];
NSURLResponse *requestResponse;
NSData *requestHandler = [NSURLConnection sendSynchronousRequest:request returningResponse:&requestResponse error:nil];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData: requestHandler options: NSJSONReadingMutableContainers error: &e];
return json;

}

这里的问题是我锁定了我的 UI,我尝试异步实现它,但是在代码尝试填充 UI 元素后很长时间数据得到 returned 什么是实现异步调用并使用正确数据填充我的 UI 元素的最佳和正确方法吗?

预计数据会在发出请求后很长时间才返回(相对于发送请求后下一行代码几乎瞬间执行而言,很长)。诀窍是推迟 UI 的更新,直到请求完成。

// optionally update the UI to say 'busy', e.g. placeholders or activity
// indicators in parts that are incomplete until the response arrives
[NSURLConnection sendAsynchronousRequest:request
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    // optionally update the UI to say 'done'
    if (!error) {
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData: requestHandler options: NSJSONReadingMutableContainers error: &e];
        // update the UI here (and only here to the extent it depends on the json)
    } else {
        // update the UI to indicate error
    }
}];

更抽象地——也更正确地——考虑正在获取的数据可能是应用程序模型的一部分。从服务器获取只是更改模型的原因之一。当模型因任何原因发生更改时,无论是通过用户操作还是此获取或其他事件,视图控制器的工作就是观察它的更改,并告诉视图进行更新。

有些情况下发出同步请求是有意义的,但如果同步请求完成时视图控制器正在等待(阻塞主线程)则不是。我已经创建了一个博客 post 来帮助深入回答这个问题:http://jasoncross-ios-development.blogspot.com/2015/04/asynchronous-json-requests-in-objective.html。 post 还讨论了有关从 Web 服务器为 iOS 应用程序消耗 JSON 的其他问题:在不同情况下应考虑哪些设计模式。

iOS 开发中最常见的模式之一是显示源自 Web 服务并通过 JSON 传输的数据。 post 讨论数据的同步和异步获取,以及其他相关设计模式。

同步和异步http请求有什么区别?在同步 http 请求中,当前正在执行的代码 "blocks"(停止并等待)直到请求完成。如果此代码在主线程上,则在进行网络调用时应用程序将出现冻结和损坏。这是一个坏主意,有悖于最佳实践,应始终避免。

相比之下,异步 http 请求允许当前正在执行的代码在请求启动和请求处于 运行 期间继续执行。请求完成后,将代码 "reports back" 发送给侦听器。在 NSURLConnection sendAsynchronousRequest:queue:completionHandler: 的情况下,侦听器是作为方法参数传入块的方法的调用者。在从主线程发出网络请求的情况下,用户界面不会锁定,应用程序会继续响应用户手势,这是公认的最佳实践。

简而言之,这就是您需要了解的全部内容:使用异步方法。但这引出了一个问题:如果不应该使用同步方法,为什么它仍然可用?答案是在很多情况下发出同步请求是有意义的。详细介绍其中一些场景构成了博客的其余部分 post。

考虑使用 "Service Layer" 发出请求,如下所示:

型号类。这些通常反映 JSON 对象 服务层。这些 类 知道 API 并进行网络调用以获取 JSON。网络调用完成后,JSON 将转换为原生模型 类(Objective-C 个对象)。 查看控制器。这些 类 处理用户交互并根据需要从服务层请求数据。

如果您的 iOS 应用程序只需要获取一次数据而不关心更新,服务层可以执行异步请求,并在请求完成时使用块更新调用方。调用者可以按照以下方式向服务层请求数据:

[serviceLayer fetchDataFromAPIWithResponseBlock:^(NSArray * arrayOfObjects, NSError *error) {

if (nil != error) {
    // deal with error appropriately
}
else if (nil != arrayOfObjects) {
    // update the user interface
}

}]; 

但是,如果您的应用程序涉及服务器或客户端上发生变化的数据,那么您将需要一种方法来协调模型变化与用户界面更新。在这种情况下,您应该考虑使用委托设计模式或观察者设计模式。如果使用委托模式,视图控制器将是服务层的委托。当模型数据改变时,服务层通知代理。在这种情况下,服务层可以使用同步请求,因为 View Controller 在等待从服务层返回时不会阻塞。实现委托模式的另一种方法是使用 NSNotificationCenter 在模型数据更改时通知视图控制器。使用委托模式和通知之间的最大决定因素是当模型数据更改时需要通知多少视图控制器。如果只有一个视图控制器,它可以成为一个委托。如果有多个视图控制器,它们都可以通过通知通知。

如果正在更改模型对象的个别属性(可能来自 iOS 应用程序的其他地方),那么您应该考虑使用键值观察 (KVO) 在模型更改时更新视图。

更深入的讨论可以在上面提到的博客 post 中找到。