【问题标题】:Swift 3 - UIView does not always display its contentSwift 3 - UIView 并不总是显示其内容
【发布时间】:2016-12-22 02:02:03
【问题描述】:

我有一个 UIViewController(主菜单),在我的其他 UIViewController(加载屏幕)完成从网络下载/同步数据后显示。我的主菜单有问题,因为它并不总是显示视图上的所有 UIButtons !存在不一致,主菜单每加载 10 次就有 1 次出现所有 UIButton。

以下是视图的外观:

以下是视图通常的显示方式:

我可以将手指放在 UIButton 应该在的位置,然后将手指移开,它们就会出现。我也可以点击它们应该在的位置,我的 segues 仍然会触发,但 UIButtons 不会自动显示。好像是

我尝试将 MainMenuView.setNeedsDisplay() 添加到 ViewDidLoad 函数,但没有帮助。我还在视图上创建了一个测试 UIButton,它触发 MainMenuView.setNeedsDisplay() 命令,但隐藏的 UIButtons 仍然隐藏。

如果我让屏幕闲置 30 秒左右,所有 UIButton 都会随机出现,而无需我手动让它们出现。

主菜单视图是正常的,如果我从应用程序的任何部分(除了加载屏幕)转到它,所有 UIButton 都是可见的。

编辑:主菜单代码 - (引用很强烈)

import UIKit
import CoreData

class MainMenuViewController: UIViewController {

    // MARK: References
    @IBOutlet var btnGasManifolds: UIButton!
    @IBOutlet var btnAirCompressors: UIButton!
    @IBOutlet var btnVacuumPumps: UIButton!
    @IBOutlet var btnUnitConversion: UIButton!
    @IBOutlet var btnCFMCalculator: UIButton!
    @IBOutlet var mainMenuView: UIView!

    var userData = [NSManagedObject]()

    // MARK: Functions

    override func viewDidLoad() {
        var name = String()
        for duserData in userData {
            name = duserData.value(forKey: "nameFull") as! String
        }
        print("Main Menu\n->\(name)")
        backgroundSetup()
    }

    override func viewDidAppear(_ animated: Bool) {
        mainMenuView.setNeedsDisplay()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func btnTest(_ sender: Any) {
        mainMenuView.setNeedsDisplay()
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any!) {
        if segue.identifier == "settingsSegue" {
            let destination = segue.destination as! SettingsViewController
            destination.userData = userData
        }
    }

    // Background Setup
    func backgroundSetup() {
        let background = UIImage(named: "Data Screens")

        var imageView : UIImageView!
        imageView = UIImageView(frame: view.bounds)
        imageView.contentMode =  UIViewContentMode.scaleAspectFill
        imageView.clipsToBounds = true
        imageView.image = background
        imageView.center = view.center
        view.addSubview(imageView)
        self.view.sendSubview(toBack: imageView)
    }
}

【问题讨论】:

  • 如果您为此视图发布代码会有所帮助。谢谢。
  • @dfd 我添加了代码。我正在试验 mainMenuView.setNeedsDisplay,所以你可以忽略它。

标签: ios swift uiview


【解决方案1】:

从服务器获取数据后创建和显示按钮的代码需要在主 UI 线程上运行。如果代码正在运行后台线程,它将无法正确显示 UI 元素,并且在显示控件之前需要一些时间或手动滚动。

在 Dispatch 主队列上运行代码。

【讨论】:

  • 在发布此问题之前,我尝试使用 DispatchQueue.Main.async 从加载屏幕触发 performSegue 函数(我也尝试过同步),但它并没有解决我的问题。 UIButton 不是以编程方式创建的,而是在 xCode 内部的情节提要上创建的。如何将创建和显示按钮的代码放在主队列上?我是否以编程方式创建按钮并在主队列中运行它?
  • 好的。我不确定我是否看到了足够的代码,但这是我的看法。首先,something 显然会造成时间(除非您已经使用所有 setNeedDisplay 和其他对视图生命周期和 segue 的调用来超越自己的代码,否则这里缺少时间)。我的猜测是,如果你去掉所有这些代码并且仍然看到问题(你可能会),我们正在谈论 db fetching。如果是这样,那么您需要在 before segue 进行编码。在你的第一个 VC 中设置它(可能会向用户发出警报),然后设置你的第二个 VC 属性和 segue。
  • 我最终让我的 UI 元素显示出来。我不得不像这样运行加载屏幕代码DispatchQueue.main.async { datasyncfunction() ; seguefunction() }
【解决方案2】:
dispatch_async(dispatch_get_main_queue(),{
   //do some work   
})

或 相应地覆盖 ViewWillLayoutSubviews 和 ViewDidLayoutSubviews 中的方法之一,并在这些方法中运行您的代码。

【讨论】:

  • 我在哪里放置调度代码?我在里面放什么内容?我的 UIButtons 不是以编程方式创建的,如果有区别的话。我需要在主队列中以编程方式创建它们吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-27
  • 1970-01-01
  • 2018-04-19
相关资源
最近更新 更多