为什么我的容器中视图中的组件不可用?

Why are the components in the view in my container not usable?

在学习 Udemy 课程时,我正在尝试制作一个简单的登录/注册界面。在我的第一个视图控制器中,我有一个垂直堆栈视图,其中包含一个标签、一个分段控件和一个容器视图。分段控件可以是 "Log In" 或 "Sign Up"。我想在分段控件更改时加载适当的视图控制器。

我的 LogInViewController 有一个垂直堆栈视图,其中包含一个用于用户名的文本字段、另一个用于密码的文本字段和一个登录按钮。我的 SignUpViewController 有一个垂直堆栈视图,其中包含用于电子邮件地址、用户名、密码和密码确认的文本字段,后跟一个注册按钮。

我的第一个视图控制器是这样的:

import UIKit

class ViewController: UIViewController, LogInViewDelegate, SignUpViewDelegate
{
    @IBOutlet weak var logInSignUpControl: UISegmentedControl!
    @IBOutlet weak var containerView: UIView!

    var logInVC: LogInViewController?
    var signUpVC: SignUpViewController?
    var activeVC = 0

    override func viewDidLoad()
    {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        initializeCustomControllers()
    }

    func initializeCustomControllers()
    {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)

        logInVC = storyboard.instantiateViewController(withIdentifier: "LogInViewController") as? LogInViewController
        signUpVC = storyboard.instantiateViewController(withIdentifier: "SignUpViewController") as? SignUpViewController

        logInVC?.delegate = self
        signUpVC?.delegate = self

        logInVC?.willMove(toParent: self)
        logInVC?.view.frame = containerView.bounds
        containerView.addSubview(logInVC!.view)
        addChild(logInVC!)
        logInVC?.didMove(toParent: self)
    }

    func swapCustomController(from: UIViewController,to: UIViewController)
    {
        from.view.removeFromSuperview()
        from.removeFromParent()

        to.willMove(toParent: self)
        to.view.frame = containerView.bounds
        containerView.addSubview(to.view)
        addChild(to)
        to.didMove(toParent: self)
     }

    @IBAction func logInSignUpControlTapped(_ sender: Any)
    {
        switch logInSignUpControl.selectedSegmentIndex
        {
        case 0:
            if activeVC == 1
            {
                swapCustomController(from: signUpVC!, to: logInVC!)
                activeVC = 0
            }
        case 1:
            if activeVC == 0
            {
                swapCustomController(from: logInVC!, to: signUpVC!)
                activeVC = 1
            }
        default:
            break
        }
    }

    func logInAttempted(error: Error?)
    {
        if error == nil
        {
            // segue
            print("log in successful")
        }
        else
        {
            showAlert(title: "Log In error",
                      message: error?.localizedDescription ?? "Unknown Error")
        }
    }

    func signUpAttempted(error: Error?)
    {
        showAlert(title: "Sign Up Error",
                  message: error?.localizedDescription ?? "Unknown Error")
    }
}

问题是,当登录或注册视图加载到容器视图中时,字段和按钮在模拟器中不可用。我无法点击文本字段并且按钮没有响应。

我尝试将对 makeFirstResponder() 的调用添加到第一个文本字段,这允许我输入文本,但按钮仍然无法使用。

在此先感谢您的帮助。

这里的主要问题可能在于 "vertical stack view" 这几个字。堆栈视图只有在由自动布局约束调整大小时才能正确运行。你的可能没有正确固定到它的超级视图。

此外,我没有看到任何代码让您解决在将容器视图的边界分配给子视图的框架后容器视图可能会调整大小的可能性。


此外,这在这里可能无关紧要,但通常请注意,您的舞步不正确:

    logInVC?.willMove(toParent: self)
    logInVC?.view.frame = containerView.bounds
    containerView.addSubview(logInVC!.view)
    addChild(logInVC!)
    logInVC?.didMove(toParent: self)

正确顺序的正确命令是:

    addChild(logInVC!)
    logInVC!.view.frame = containerView.bounds
    containerView.addSubview(logInVC!.view)
    logInVC!.didMove(toParent: self)

在子视图控制器视图没有响应的一般问题中,要么是因为插座没有连接,要么是因为视图控制器已被允许掉在地板上,导致视图没有人可以与之交谈。

但是,在您的情况下,很可能是因为堆栈视图未正确配置,按钮最终超出了其父视图的范围。 (您可以使用 View Debugger 来确认该假设。)在其父视图之外的视图是可见的,但不可触摸。