UIActivityIndi​​cator 在构建 UIView 层次结构时旋转?

Posted

技术标签:

【中文标题】UIActivityIndi​​cator 在构建 UIView 层次结构时旋转?【英文标题】:UIActivityIndicator spinning while UIView hierarchy being constructed? 【发布时间】:2012-11-02 10:00:12 【问题描述】:

有没有办法在构建复杂的 UIView 层次结构时为 UIActivityIndi​​cator 设置动画?我有一个复杂的层次结构,要通过'viewDidLoad'中的'addSubview:'添加(在一个主要的故事板项目中,但这个场景是动态创建的)。不摆弄 GCD,只要初始化需要,UI 就会阻塞。将初始化放入“dispatch_sync”(如下所示)不会显示/动画指示器,将其放入“dispatch_async (dispatch_get_global_queue (0,0),...”会导致崩溃(因为 UIKit 代码需要在主队列上运行? ),并将其放入 'dispatch_async (dispatch_get_main_queue(),...' 会造成死锁(我猜是苹果公司宣布的那样)。

-(void)viewDidLoad 
    dispatch_sync (dispatch_get_global_queue (0,0), ^
        // initialization here
        )

那么前进的方向是什么?

【问题讨论】:

【参考方案1】:

把代码放到方法里试试

– performSelectorOnMainThread:withObject:waitUntilDone:
– performSelectorOnMainThread:withObject:waitUntilDone:modes:

【讨论】:

Sunkehappy,我也试过这个:将初始化放入一个新方法中,并使用 'performSelectorOnMainThread' 在 'viewDidLoad' 中调用它。不幸的是,什么都没有改变:在初始化期间,旧屏幕显示没有微调器,初始化后,微调器在屏幕上短暂闪烁,然后 segue 动画进入第二个屏幕。 你说微调器在屏幕上闪烁。这是否意味着子视图添加成功?那么你能试着找出它为什么会“飞溅”,为什么会消失吗? 好吧,用断点乱扔代码,我看到微调器已正确添加,但在所有初始化过程中它仍然静止('performSegueWithIdentifier'、'viewDidLoad'、'viewWillAppear' 都被正确调用) .只有在离开 'viewWillAppear' 后完成转场的最终动画(在我的情况下是翻转)时,它才会开始旋转。【参考方案2】:

为什么不在 viewDidLoad 中启动活动指示器,然后使用 performSelectorInBackground 安排初始化:

-(void)viewDidLoad 
    [super viewDidLoad];
    [self.activityIndicator startAnimating];
    [self performSelectorInBackground:@selector(finishInitializing) withObject:nil];


-(void)finishInitializing 
    // finish resource-intensive setup
    // ...

    dispatch_async(dispatch_get_main_queue(), ^
        [self.activityIndicator removeFromSuperview];
        // create view hierarchy
        // ...
    );

这允许viewDidLoad 返回,以便微调器可以在主线程上进行动画处理。

【讨论】:

克里斯托弗,感谢您的回答。但是,“performSelectorInBackground:”创建了一个新线程,它显然不再是主线程(= UI 线程),并且在那里调用 UIKit 崩溃并抱怨这不是正确的线程。 是的,我的想法是您在该线程上进行资源密集型工作,然后在 dispatch_async 调用中完成主线程上的 UI 布局。 “复杂的 UIView 层次结构”中的任何缓慢几乎肯定不是在 UIKit 中,而是在您为准备布局所做的任何事情中。您永远不需要活动指示器来布置视图。 初始化中所做的是从 CoreData 中提取对象(表示平面图上的区域)并相应地构建视图。我知道这些区域的渲染性能可能仍然存在问题(我删除了视觉设计想要使其响应足够拖动的阴影),但我想认为渲染只发生在可见区域。 您不应该在后台线程上加载 Core Data 对象并将它们交给主线程。它可能导致极难重现的崩溃。我们有一个类似的用例,我们在后台加载 CD,将必要的字段复制到值对象中,然后在主队列上的 dispatch_async 调用中使用这些值对象进行渲染。我们最初将 CD 对象直接传递到主队列块,并且在测试中从未遇到过崩溃,但在野外报告了几次崩溃。 也许你遇到了和我一样的陷阱(最近才浮出水面,但与这里的问题无关):CD 在涉及线程时需要一些预防措施 - 永远不要在不同的线程中回收一个 NSManagedObjectContext,永远不要通过线程之间的 NSManagedObjects。它写在 CD 编程指南的“并发”标题下。

以上是关于UIActivityIndi​​cator 在构建 UIView 层次结构时旋转?的主要内容,如果未能解决你的问题,请参考以下文章

重新加载 UICollectionView 时 UIActivityIndi​​cator 不会停止

UIActivityIndi cator添加AppDelegate

UICollectionView 单元格中的 UIActivityIndi​​cator 随机不会隐藏

在 UIButton 中放置一个 UIActivityIndi​​cator

如何在 UITableView 的 searchBar 上方显示 UIActivityIndi​​cator

我可以更改 UIActivityIndi​​cator 的大小吗?