GCD:UIViews 上的两个并行动画

Posted

技术标签:

【中文标题】GCD:UIViews 上的两个并行动画【英文标题】:GCD: two parallel animations on UIViews 【发布时间】:2014-05-17 18:50:36 【问题描述】:

我来自这篇文章,因为讨论偏离了主要问题。 Behavior of GCD async method not understandable

请帮忙,

我的 iPad 应用程序有两个并排的 TableView。 这两个必须从两个不同的 Web 服务实时加载数据。 我想要两个线程 - 每个线程都专用于一个 tableview。 由于 dispatch_get_main_queue 只会给我一个串行的,我将无法真正实时更新表。而且,它还涉及更新 UI 元素,我只需要在主队列上进行线程处理,这是串行的 - 使得并行获取不可能。

有人可以添加您的想法,让我告诉我如何让两个单独的线程同时运行并更新 UI 元素?

【问题讨论】:

查看“View Programming Guide for ios”和“Core Animation Programming Guide”中的“Animations”。有专门的方法可以为视图和图层设置动画。 @MartinR:请看这个场景。我已经改变了我的问题。如果您对这个问题投了反对票,能否请您重置该反对票? 我没有对这个问题投票。 - 但你应该更清楚地描述你的问题,它似乎与 UView 动画无关。请注意,您可以在后台线程上获取数据,并且只有在数据到达时才在主线程上进行 UI 更新。 【参考方案1】:

你问:

有人可以添加您的想法,让我告诉我如何让两个单独的线程同时运行并更新 UI 元素?

您可以简单地让这些线程在后台线程中执行它们的请求和解析,然后让它们将模型和 UI 更新分派回主队列。

例如,您可以执行以下操作:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
   // issue first web service request

   // when done, update the UI

   dispatch_async(dispatch_get_main_queue(), ^
       // update the model here

       // also issue the `reloadData` (or whatever table updates you want) 
       // for the first table view
   );
);

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
   // issue second web service request

   // when done, update the UI

   dispatch_async(dispatch_get_main_queue(), ^
       // update the model here

       // also issue the `reloadData` (or whatever table updates you want) 
       // for the second table view
   );
);

这两个将并发运行(因为所有全局队列都是并发队列),但 UI/模型更新将被分派到主队列,这将确保一切保持同步,UI 更新成功发生等。因此您可以享受后台队列提供并发,但您将在需要的地方利用串行主队列。

显然,以上假设您将网络请求分派到某个后台队列(我们将使用默认的全局队列),但是发出异步网络请求的精确机制可能会有很大差异(并且可能不涉及任何完全派遣)。如果你需要具体的建议,你应该准确地分享你是如何向你的网络服务发出请求的(例如 AFNetworking?NSURLConnection(如果NSURLConnection,一种便利方法或基于委托的方法)?NSURLSession? ),因为实施细节将根据您提出请求的方式而有所不同。

但想法很简单:异步执行网络服务请求,然后确保在请求完成后,在主队列上执行生成的模型和 UI 更新。这样,您可以享受请求的并发性,但 UI 更新发生在主队列上。

【讨论】:

嗨,罗伯。谢谢!在主 dispatch_async 内部,不应该是 dispatch_sync(),因为在初始化之后我想更新我的 UI。如果我错了,请纠正我。 @Chandu 你可以使用dispatch_sync 如果你愿意,但这里没有必要。我通常会建议dispatch_async,除非有迫切的需要(即,您在调度后立即有一些东西在调度的代码完成之前不应该开始)。但这里不是这种情况(至少在我的示例代码中)。但是dispatch_syncdispatch_async的区别在这里并不显着,所以有点学术。【参考方案2】:

是的,您只能在主线程上更新 UI。

如果您使用UIView animateWithDuration:... animations:...,您可以在动画块中的多个不同视图上放置多个动画,以便它们同时运行。您也可以反复拨打animateWithDuration:animations:

对于图层,您可以使用CAAnimationGroup 对动画进行分组以便并发执行。

在任何情况下,您都不应该使用(或尝试使用)GCD 来制作 UI 动画。

【讨论】:

我已经改变了我的问题。请看 所以这是一个完全不同的问题...... Web 服务不会同时返回数据,因此期望并发 UI 更新是错误的。请参阅@MartinR 的评论,了解您应该做什么。 我提到了两种不同的网络服务。如果这些都是单核处理器,那么在给定的最小可能时间片内不会发生任何事情。但是,当我们确实有内核时,有可能在给定的时间在不同的内核上发生两件事。 您在谈论宏观时间(网络响应)和微观时间(时钟周期),就像它们是同一件事一样。您是否真的有问题,因为您所描述的不是问题,而是一个无效的问题。

以上是关于GCD:UIViews 上的两个并行动画的主要内容,如果未能解决你的问题,请参考以下文章

使用自动布局对齐两个 uiviews

如何在 UIScrollView 中的对象(UIViews)上执行翻转动画

如何为具有约束的 UIView 设置动画?

当我们在运行时更改模拟器方向时,UIViews 重叠

SKSpriteNode 动画渐变

Objective-C IOS多线程之GCD深入理解