将新的视图控制器推送到我的导航控制器时,我返回的视图控制器与我点击的视图控制器相同,而不是新的视图控制器

When pushing a new view controller to my navigation controller, I get returned the the same view controller I tapped from instead of the new one

提问人:ilmfeemster 提问时间:10/23/2023 更新时间:10/23/2023 访问量:31

问:

我有一个UIViewController,它添加了一个UITableView作为子视图。当我点击单元格以返回新的 UIViewController(详细信息视图控制器,除背景颜色外为空)时,我返回相同的起始视图控制器和表视图。

我正在使用 navigationController.pushViewController(),但我对 present() 有同样的问题。我被引导相信我调用了错误的视图控制器,但是当使用调试视图层次结构时,我的详细信息视图控制器似乎是主视图控制器的副本。我无法弄清楚为什么,因为详细视图控制器大部分是空的。我还确定我已经正确设置了场景委托,并将导航控制器设置为根视图。

这是 tableView 代码,变量 “countries” 是一个字符串数组。我试过使用self.navigationController?。pushViewController(),并且没有任何变化。


extension ViewController : UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return countries.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: FlagCell.identifier, for: indexPath) as! FlagCell
        let country = countries[indexPath.row]
        let image = UIImage(named: country)
        cell.flagImageView.image = image
        cell.countryNameLabel.text = country
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let vc = FlagViewController()
        navigationController?.pushViewController(vc, animated: true)
    }
}

下面是详细信息视图控制器的代码。

import UIKit

class FlagViewController: ViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .systemMint
    }
}
Swift UITableView UIViewController UIKit的

评论


答:

0赞 Duncan C 10/23/2023 #1

这一行可能是您的问题:

let vc = FlagViewController()

如果创建这样的视图控制器,则它不会从情节提要或 nib 文件中获取视图。据我所知,通过调用没有此类参数的初始值设定项来创建视图控制器的唯一方法是,如果该视图控制器实现方法并在代码中构建其视图层次结构。loadView()

除非您在代码中创建了视图层次结构,否则您可能希望使用 方法从 Storyboard 加载它。FlagViewControllerUIStoryboardinstantiateViewController(withIdentifier:)

评论

0赞 ilmfeemster 10/23/2023
确定更新,该应用程序正在发送 2 个视图,主视图和详细信息视图。如果我减少约束,我可以在详细信息视图下方看到新的表视图加载。
0赞 Duncan C 10/23/2023
您说“应用程序正在发送 2 个视图......”我不知道“发送视图”是什么意思。使用特定的、适当的术语,例如“推送”(到导航堆栈上)或“演示”(模态)。
0赞 Duncan C 10/23/2023
此外,不要混淆视图和视图控制器。视图是显示在屏幕上的内容。视图控制器实现业务逻辑并管理视图。它们不是一回事,如果你混淆了这些术语,你会造成混淆(对自己和他人)。
0赞 ilmfeemster 10/24/2023
好的,谢谢你的解释和建议。我的详细信息视图控制器类符合“ViewController”(我的主视图控制器的名称)而不是“UIViewController”,因此它从两个类推送子视图。
0赞 ilmfeemster 10/23/2023 #2

谢谢,似乎我需要更多视图层次结构代码,我很困惑,因为我看过许多教程和文章,这些教程和文章的代码与我的代码相同,可以完成类似的工作,但事实就是如此。我使用了viewDidLoad(),但请告诉我是否建议使用didLoad()

这是新 viewController 的最终更新

let flagView: UIView = {
    let flagView = UIView()
    flagView.backgroundColor = .systemMint
    return flagView
}()

override func viewDidLoad() {
    super.viewDidLoad()
    setupUI()
}


// MARK: - UI Setup
private func setupUI() {
    self.view.addSubview(flagView)
    flagView.translatesAutoresizingMaskIntoConstraints = false
    
    
    NSLayoutConstraint.activate([
        flagView.topAnchor.constraint(equalTo: self.view.topAnchor),
        flagView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
        flagView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
        flagView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
        
        flagView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
        flagView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
    ])
}

评论

0赞 Duncan C 10/23/2023
你错过了我回答中的关键点:每次你的用户选择你的类中的一个单元格时,你都会创建一个新的实例,并将其呈现在UI中现有的一堆模态之上。这是错误的。ViewControllerFlagViewController