子视图永远不可见

Posted

技术标签:

【中文标题】子视图永远不可见【英文标题】:Child view is never visible 【发布时间】:2017-07-31 06:46:46 【问题描述】:

我正在以编程方式构建我们的 UI,但在为子视图渲染元素时遇到了一些麻烦。

我正在通过实例化我的初始视图控制器及其所需的视图来设置应用程序 Window

class AppDelegate: UIResponder, UIApplicationDelegate 

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 

        let initialView = StartupView(frame: CGRect.zero)
        let startupViewController = StartupViewController(startupView: initialView);

        window = UIWindow(frame: UIScreen.main.bounds);
        window!.rootViewController = startupViewController;
        window?.backgroundColor = UIColor.white
        window!.makeKeyAndVisible();

        return true
    

StartupView 类实例化单个 UIButton,它添加到自身并设置约束以指定高度/宽度并水平和垂直居中对齐。

class StartupView : UIView 

    // views
    var newAccountButton: UIButton!

    override init(frame: CGRect) 
        super.init(frame: frame)
        self.configureView()
    

    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        self.configureView()
    

    override func updateConstraints() 
        self.newAccountButton.translatesAutoresizingMaskIntoConstraints = false
        self.newAccountButton.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
        self.newAccountButton.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
        self.newAccountButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
        self.newAccountButton.widthAnchor.constraint(equalToConstant: 50).isActive = true

        print("\(self.newAccountButton.titleLabel?.text ?? "Unknown") is \(self.newAccountButton.frame)")
        super.updateConstraints()
    

    func configureView() 
        // New account button setup
        newAccountButton = UIButton(frame: CGRect.zero)
        newAccountButton.titleLabel?.text = "Create Account"

        self.addSubview(newAccountButton)
    

StartupView 被赋予其ViewController。似乎分配给StartupViewViewController 约束正在工作,因为我已经验证我的StartupView 的大小确实与ViewController 视图的大小相等。但是,当我运行模拟器时,我看不到 UIButton

class StartupViewController: UIViewController 
    var startupView: StartupView!

    init(startupView: StartupView) 
        self.startupView = startupView
        super.init(nibName: nil, bundle: nil)
    

    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        self.startupView = StartupView(frame: CGRect.zero)
    

    override func viewDidLoad() 
        super.viewDidLoad()
        self.view.addSubview(self.startupView)

        self.startupView.translatesAutoresizingMaskIntoConstraints = false

        self.startupView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
        self.startupView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
        self.startupView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        self.startupView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true

        self.startupView.updateConstraints()
    

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

我做错了约束吗?或者我添加嵌套视图的顺序重要吗?

编辑

这是视图调试器的截图。

我可以看到布局中的按钮(突出显示),但看不到正在呈现的实际按钮。写print("\(self.newAccountButton.titleLabel?.text): \(self.newAccountButton.frame)") 会写出按钮的标题和它的框架,但没有呈现任何内容。

【问题讨论】:

你不应该自己打电话给updateConstraints()。相反,您应该调用setNeedsUpdateConstraints() 并让布局引擎处理其余的事情。此外,请确保不要在 updateConstraints() 中再次添加相同的约束,因为此方法可以多次调用。 谢谢 - 我更新了我的代码以使用 setNeedsUpdateConstraints()。它没有解决我最初的问题,但至少我知道请求约束更新的正确方法:) 【参考方案1】:

我认为您可以简单地这样做,而不是覆盖 updateConstraints:

编辑

与OP聊天讨论后的最终解决方案(不直接访问标签):

    func configureView() 
        // New account button setup
        newAccountButton = UIButton(frame: CGRect.zero)
        newAccountButton.setTitleColor(self.tintColor, for: UIControlState.normal)

        newAccountButton.setTitle("Create Account", for: UIControlState.normal)

        self.addSubview(newAccountButton)
        self.newAccountButton.translatesAutoresizingMaskIntoConstraints = false
        self.newAccountButton.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
        self.newAccountButton.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
        self.newAccountButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
        self.newAccountButton.widthAnchor.constraint(equalToConstant: 50).isActive = true
    

【讨论】:

当应用程序运行时,StartupView 中仍然缺少该按钮:/ 我还在configureView() 函数的末尾添加了setNeedsUpdateConstraints(),但它没有任何区别 你是否从 StartupViewController viewDidLoad 中删除了 self.startupView.updateConstraints() 我做到了 - 没有任何影响 您是否删除了您覆盖的 updateConstraints 方法 我做到了,我更新了我的 OP 以显示调试器的屏幕截图。看起来约束正在起作用;但是什么都没有渲染。【参考方案2】:

我认为在您的应用委托中,您必须定义 StartupView 的大小。目前设置为zero

let initialView = StartupView(frame: CGRect.zero).

【讨论】:

启动视图在构建StartupView 约束时获取由StartupViewController 设置的大小。这没有问题

以上是关于子视图永远不可见的主要内容,如果未能解决你的问题,请参考以下文章

IOS:UIView 永远可见

XIB 子视图不可见

CAGradientLayer 导致子视图不可见

Xcode - 子视图不可见

当作为子视图添加到集合视图单元格时,滚动视图中的内容不可见

我是不是需要删除 UIScrollView 中不可见的子视图以使其平稳运行?