【问题标题】:iOS - UITableView inside a UIViewiOS - UIView 内的 UITableView
【发布时间】:2019-03-04 01:29:21
【问题描述】:

我想在UIViewController 中显示UITableView。这个 View Controller 包含一个带有两个屏幕的UISegmentedControlFirstViewControllerSecondViewController)。

第一个 View Controller 是包含 UIViewTable 的那个(请不要介意第二个)。

当我在模拟器中执行应用程序时,一切正常,但是当我尝试在第一个 ViewController 中滚动表格视图时,单元格消失了。让它们重新出现的唯一方法是终止应用并重新打开它。

我是 iOS 开发的新手(我来自 Android),我显然在这里遗漏了一些东西。

我已经尝试在容器 UIView 之外添加一个 UIViewTable 并且效果很好。所以我猜这个问题与容器或分段控件有关......

这是我的实现:

  • 故事板

UIViewControllerUISegmentedControlUIView(将包含分段控件的两个屏幕)。

  • 视图控制器

    @IBOutlet weak var container: UIView!
    var sectionViews:[UIView]!
    
    override func viewDidLoad() {
         super.viewDidLoad()
    
         sectionViews = [UIView]()
         sectionViews.append(FirstViewController().view)
         sectionViews.append(SecondViewController().view)
         for v in sectionViews {
            container.addSubview(v)
         }
         container.bringSubviewToFront(sectionViews[0])
    }
    
    @IBAction func switchViewsAction(_ sender: UISegmentedControl) {
         self.container.bringSubviewToFront(self.sectionViews[sender.selectedSegmentIndex])
    }
    
  • 第一个视图控制器

FirstViewController 有一个swift 和一个xib 文件,并且有两个文件Cell.swiftCell.xib 用于表格单元格。

FirstViewController.swift

@IBOutlet weak var tableView: UITableView!
let cellID = "CellId"

override func viewDidLoad() {
    super.viewDidLoad()

    self.tableView.register(UINib(nibName: "Cell", bundle: nil), forCellReuseIdentifier: cellID)
    self.tableView.dataSource = self
    self.tableView.delegate = self
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 100
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = self.tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! Cell
    cell.label.text = "\(indexPath.row)"
    return cell
}

FirstViewController.xib

Cell.xib

任何帮助将不胜感激! 谢谢

【问题讨论】:

    标签: ios swift uitableview


    【解决方案1】:

    一个明显的问题是你说container.addSubview(v) 没有给v 任何框架或约束。既然你使用自动布局来定位container,你也应该使用自动布局来定位v。您应该将其顶部、底部、前导和尾随锚点设置为等于 container 的锚点,constant 为零。 (并将其translates... 设置为false。)对循环中v 的两种情况都这样做。

    但是,还有一个更严重的问题,即您通过说FirstViewController()SecondViewController() 创建的视图控制器没有被保留。于是,他们就烟消云散了。它们因此失去了功能;例如,表格视图不再有任何数据源或委托,因此它没有单元格。

    你的所作所为是完全违法的。您不能简单地使用视图控制器“dumpster-dive”作为抓取其视图并将其视图推入界面的方式,不管是哪一种。您必须使视图控制器成为父视图控制器(在本例中为 Item)的 child 视图控制器。为了确保子视图控制器在视图控制器层次结构中具有适当的位置,并以良好的顺序接收视图控制器必须接收的所有消息,您必须进行精心设计的舞蹈,而您没有在跳舞。

    有关如何跳舞的示例,请参阅我的答案

    【讨论】:

    • 尽管您的方法中存在这些错误,但我还是要祝贺您提出了一个问得非常好的问题。你非常出色地展示了为了彻底理解你在做什么所必需的一切。这很难做到。
    • 进一步评论:当用户一次只能看到一个视图控制器的视图时,我不建议保留两个视图控制器及其视图。没有必要重新发明这个轮子。您最好使用标签栏控制器之类的东西,甚至更好的是为这种事情设计的页面视图控制器。
    • 谢谢马特。我会试试你的建议!知道这个问题有足够的细节让人放心,我一直担心它太长了......
    【解决方案2】:
    import UIKit
    
    class TestViewController: UIViewController , UITableViewDataSource, UITableViewDelegate{
    
        @IBOutlet weak var segmentControlOutlet: UISegmentedControl!
        @IBOutlet weak var tableView: UITableView!
        var arrayName = ["Label1", "Label2", "Label3","Label4","Label5","Label6","Label7","Label8","Label9","Label10"]
        var arrayName2 =  ["Label1", "Label2", "Label3","Label4","Label5"]
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    
        @IBAction func segmentControlAction(_ sender: UISegmentedControl) {
            self.tableView.reloadData()
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            if segmentControlOutlet.selectedSegmentIndex == 0 {
                return arrayName.count
    
            }else{
                return arrayName2.count
    
            }
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableViewCell", for: indexPath) as! TestTableViewCell
            if segmentControlOutlet.selectedSegmentIndex == 0 {
                cell.textLabel?.text = arrayName[indexPath.row]
    
            }else{
                 cell.textLabel?.text = arrayName2[indexPath.row]
            }
            return cell
        }
    
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return 50
        }
    }
    

    这段代码是针对 UITableViewCell 类的:-

    import UIKit
    
    class TestTableViewCell: UITableViewCell {
        @IBOutlet weak var labelName: UILabel!
    
        override func awakeFromNib() {
            super.awakeFromNib()
            // Initialization code
        }
    
        override func setSelected(_ selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
    
            // Configure the view for the selected state
        }
    
    }
    

    【讨论】:

    • 感谢您的回答,但是它对分段控件的两个部分没有使用不同的视图控制器,只有两个列表。
    • 在 Segment Action 上,您可以这样做以移动到下一个 viewController: if segmentControlOutlet.selectedSegmentIndex == 0 { let vc = self.storyboard?.instantiateViewController(withIdentifier: "AViewController") as! AViewController self.navigationController?.pushViewController(vc, animated: true) }else{ let vc = self.storyboard?.instantiateViewController(withIdentifier: "BViewController") as! BViewController self.navigationController?.pushViewController(vc, animated: true) }
    猜你喜欢
    • 2012-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 1970-01-01
    相关资源
    最近更新 更多