Swift/iOS 子视图在主线程上未立即显示

Posted

技术标签:

【中文标题】Swift/iOS 子视图在主线程上未立即显示【英文标题】:Swift/iOS Subview Not Showing Immediately, on Main Thread 【发布时间】:2014-12-30 04:08:38 【问题描述】:

所以我要循环添加几个子视图到我的 ViewController 的视图中;问题是从我添加子视图开始出现约 5 秒的延迟。 添加后,我确保在子视图和我的视图上都调用 setNeedsDisplay,没有骰子。我什至使用NSThread.isMainThread() 仔细检查了代码 是否在主线程 上执行,并且它按预期返回true。这是我的确切代码:

    dispatch_async(dispatch_get_main_queue()) 
        var nib = UINib(nibName: "ProfileCard", bundle: NSBundle.mainBundle())
        var profiles = self.delegate.user!.profilesToShow

        //loop to add ProfileCard subviews
        while profiles.count > 0 && self.deck.count < self.MAX_DECK_SIZE 
            println("Adding Card")

            //setup subview
            var card = nib.instantiateWithOwner(self, options: nil).first! as ProfileCard
            card.delegate = self
            card.frame = CGRect(x: (self.view.bounds.width - 300)/2, y: 100, width: 300, height: 200)
            card.displayProfile(profiles.first!)

            //add subview
            self.view.addSubview(card)
            self.view.sendSubviewToBack(card)
            card.setNeedsDisplay()
            self.view.setNeedsDisplay()

            //add card to deck, mark as shown
            self.deck.append(card)
            profiles.removeAtIndex(0)
        
    

此循环中的任何打印语句在子视图实际显示之前约 5 秒运行,我不确定这是由于什么原因。我什至在子视图的 init 方法中设置了打印语句,甚至是那些以预期打印的语句。

【问题讨论】:

这段代码究竟是从哪里调用的?它是什么方法的摘录? 这是网络请求后通过 NSNotification 触发的方法的摘录。发生网络请求,触发此方法,并且应该创建和添加子视图(这就是这段代码的内容)。但是这段代码会运行,然后在子视图出现在屏幕上之前会有一段延迟。 所以你有其他代码被通知在后台线程上运行? that 代码是否尝试与后台线程上的接口对话?这可能是问题的原因。 您是否急于收到所有printlns,然后是延迟,然后是所有绘图? 这是通知调用的全部代码。为了简单起见,我只是摆脱了方法签名。我相信,这段代码“与之对话”的所有内容都已加载到内存中。 【参考方案1】:

这段代码可能没有在后台线程上运行,但您必须进入主线程这一事实表明您还有其他 em> 在后台线程上运行的代码。其他代码是问题的根源。它正在尝试与后台线程上的界面对话。这反过来又会破坏整个绘图系统。

【讨论】:

我愿意,我的网络请求发生在一个单独的线程上。但据我所知,这与后台线程之间没有发生通信。唯一来自后台的是var profiles = self.delegate.user!.profilesToShow 行,其中profilesToShow 是由单独线程填充的数组。但这就是我制作临时副本的原因...嗯:/ 另外,如果发生通信,会不会在 while 循环本身内有延迟?但这一切似乎都是同时发生的,而绘图是唯一延迟的事情。 绘图是一个特殊的过程。当您的代码运行时,不会发生绘图。只有在所有代码完成后(当 CATransaction 提交时),才会进行绘图。因此,可以通过尝试在后台线程上与 整个 绘图系统进行对话来搞砸它。 哦,甚至制作一个副本(如果即使 一个副本),您也可以在self.delegate.user!.profilesToShow 上发生线程冲突。这不是将这些数据线程安全地向下传递到主线程的方式。 好吧,你可以进入主线程做一些事情,然后再回到后台线程。只是不要从两个不同的线程处理相同的空间。永远。

以上是关于Swift/iOS 子视图在主线程上未立即显示的主要内容,如果未能解决你的问题,请参考以下文章

守护线程

视图不会立即显示

Toast 运行在主线程

Swift(iOS)将UIImage数组插入子视图?

启用即时应用功能的已发布 Play 商店应用程序上未显示“立即尝试”按钮

ios 滑动手势在子视图上未被识别,父视图上的手势