【问题标题】:Create UITableView programmatically in Swift在 Swift 中以编程方式创建 UITableView
【发布时间】:2017-03-06 09:03:43
【问题描述】:

我尝试在不使用 xib 或 Storyboard 的情况下以编程方式实现 UITableView。这是我的代码:

ViewController.swift

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let table: UITableViewController = MyTableViewController()
        let tableView: UITableView = UITableView()
        tableView.frame = CGRect(x: 10, y: 10, width: 100, height: 500)
        tableView.dataSource = table
        tableView.delegate = table

        self.view.addSubview(tableView)
    }
}

MyTableViewController.swift

import UIKit

class MyTableViewController: UITableViewController {

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        NSLog("sections")
        return 2
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        NSLog("rows")
        return 3
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        NSLog("get cell")
        let cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "Cell")
        cell.textLabel!.text = "foo"
        return cell
    }  
}

但是当我运行应用程序时,我得到的只是空表。在日志中,我看到几行 sectionsrows,但没有看到 get cell。如何修复此代码以获取包含 6 行 foo 文本的表格?

【问题讨论】:

  • 为什么ViewController 有自己的表格视图,MyTableViewController 也有自己的表格视图?
  • MyTableViewControllerviewDidLoad 之后发布。所以试着保留一个参考。
  • 如果您是 iOS 和 Swift 的新手,我强烈建议您遵循网络或 iTunesU 上的教程。 iTunesU 上名为Developing iOS 9 Apps with Swift 的斯坦福课程将解释对象图以及如何使用 iOS 框架。
  • 感谢您的回答,New16 的回答帮助了我。

标签: ios swift uitableview


【解决方案1】:

使用UITableViewController 作为视图控制器表视图的数据源和委托是没有意义的。您自己的视图控制器应该是表格视图的数据源和委托。

由于您似乎想要一个带有不占用整个视图的表格视图的视图控制器,因此将所有内容移至您的视图控制器,如下所示:

ViewController.swift:

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let tableView: UITableView = UITableView()
        tableView.frame = CGRect(x: 10, y: 10, width: 100, height: 500)
        tableView.dataSource = self
        tableView.delegate = self

        self.view.addSubview(tableView)
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        NSLog("sections")
        return 2
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        NSLog("rows")
        return 3
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        NSLog("get cell")
        let cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "Cell")
        cell.textLabel!.text = "foo"
        return cell
    }  
}

【讨论】:

  • 我认为 OP 想要创建一个远离 VC 的结构(或数据模型)?
【解决方案2】:

你不需要为 UITableView 创建一个单独的类。只需在您的 ViewController 类中实现 UITableViewDelegate 和 UITableViewDataSource 协议,然后实现委托方法。 我认为你的代码应该是这样的

class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource {

    override func viewDidLoad() {
        super.viewDidLoad()

        let table: UITableViewController = MyTableViewController()
        let tableView: UITableView = UITableView()
        tableView.frame = CGRect(x: 10, y: 10, width: 100, height: 500)
        tableView.dataSource = table
        tableView.delegate = table

        self.view.addSubview(tableView)
    }
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        NSLog("sections")
        return 2
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        NSLog("rows")
        return 3
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        NSLog("get cell")
        let cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "Cell")
        cell.textLabel!.text = "foo"
        return cell
    } 
}

如果您仍然遇到问题,请告诉我们更多信息或显示日志。

【讨论】:

    【解决方案3】:

    注意:正如你提到的,你刚刚开始在Swift 编程。我以编程方式创建了一个 tableView。 Copypaste 将下面的代码放入您的 viewController运行项目...

    import UIKit
    
    class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
        private let myArray: NSArray = ["First","Second","Third"]
        private var myTableView: UITableView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let barHeight: CGFloat = UIApplication.shared.statusBarFrame.size.height
            let displayWidth: CGFloat = self.view.frame.width
            let displayHeight: CGFloat = self.view.frame.height
    
            myTableView = UITableView(frame: CGRect(x: 0, y: barHeight, width: displayWidth, height: displayHeight - barHeight))
            myTableView.register(UITableViewCell.self, forCellReuseIdentifier: "MyCell")
            myTableView.dataSource = self
            myTableView.delegate = self
            self.view.addSubview(myTableView)
        }
    
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            print("Num: \(indexPath.row)")
            print("Value: \(myArray[indexPath.row])")
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return myArray.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath as IndexPath)
            cell.textLabel!.text = "\(myArray[indexPath.row])"
            return cell
        }
    }
    

    输出:

    【讨论】:

    • 我在尝试注册原型单元时遇到错误。任何解决方案或解决方法。我正在使用 swift 4
    • @ZahurafzalMirza 上面的代码在 Swift 4 中应该可以正常工作。你的错误日志说什么?
    • @Joe didSelectRowAt 方法未调用,
    • 如何像添加图片一样自定义tableCell元素?和每行中的单元格计数?
    • @Criss 你必须创建一个 customTableviewCell 来添加图像等。按照这个教程可能会有所帮助ralfebert.de/ios-examples/uikit/uitableviewcontroller/…
    【解决方案4】:

    为 Swift 3 更新

    选项 1:

    import UIKit
    //
    // MARK :- TableViewController
    //
    class TableViewController: UITableViewController {
    
        private let headerId = "headerId"
        private let footerId = "footerId"
        private let cellId = "cellId"
    
        //
        // MARK :- HEADER
        //
        override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    
            return 150
        }
    
        override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    
            let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: headerId) as! CustomTableViewHeader
            return header
        }
    
        //
        // MARK :- FOOTER
        //
        override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    
            return 150
        }
    
        override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
    
            let footer = tableView.dequeueReusableHeaderFooterView(withIdentifier: footerId) as! CustomTableViewFooter
            return footer
        }
    
        //
        // MARK :- CELL
        //
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    
            return 1
        }
    
        override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    
            return 150
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
            let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! CustomTableCell
            return cell
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            title = "TableView Demo"
            view.backgroundColor = .white
            setupTableView()
        }
    
        func setupTableView() {
    
            tableView.backgroundColor = .lightGray
            tableView.register(CustomTableViewHeader.self, forHeaderFooterViewReuseIdentifier: headerId)
            tableView.register(CustomTableViewFooter.self, forHeaderFooterViewReuseIdentifier: footerId)
            tableView.register(CustomTableCell.self, forCellReuseIdentifier: cellId)
        }
    }
    
    //
    // MARK :- HEADER
    //
    class CustomTableViewHeader: UITableViewHeaderFooterView {
    
        override init(reuseIdentifier: String?) {
            super.init(reuseIdentifier: reuseIdentifier)
    
            contentView.backgroundColor = .orange
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    
    //
    // MARK :- FOOTER
    //
    class CustomTableViewFooter: UITableViewHeaderFooterView {
    
        override init(reuseIdentifier: String?) {
            super.init(reuseIdentifier: reuseIdentifier)
    
            contentView.backgroundColor = .green
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    
    //
    // MARK :- CELL
    //
    class CustomTableCell: UITableViewCell {
    
        override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
    
            contentView.backgroundColor = .white
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    

    选项 2: 将上面的 选项 1 TableViewController 替换为这个类

    import UIKit
    //
    // MARK :- ViewController
    //
    class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
        private let headerId = "headerId"
        private let footerId = "footerId"
        private let cellId = "cellId"
    
        lazy var tableView: UITableView = {
    
            let tv = UITableView(frame: .zero, style: .plain)
            tv.translatesAutoresizingMaskIntoConstraints = false
            tv.backgroundColor = .lightGray
            tv.delegate = self
            tv.dataSource = self
            tv.register(CustomTableViewHeader.self, forHeaderFooterViewReuseIdentifier: self.headerId)
            tv.register(CustomTableViewFooter.self, forHeaderFooterViewReuseIdentifier: self.footerId)
            tv.register(CustomTableCell.self, forCellReuseIdentifier: self.cellId)
            return tv
        }()
    
        //
        // MARK :- HEADER
        //
        func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    
            return 150
        }
    
        func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    
            let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: headerId) as! CustomTableViewHeader
            return header
        }
    
        //
        // MARK :- FOOTER
        //
        func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    
            return 150
        }
    
        func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
    
            let footer = tableView.dequeueReusableHeaderFooterView(withIdentifier: footerId) as! CustomTableViewFooter
            return footer
        }
    
        //
        // MARK :- CELL
        //
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    
            return 1
        }
    
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    
            return 150
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
            let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! CustomTableCell
            return cell
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            title = "TableView Demo"
            view.backgroundColor = .white
            view.addSubview(tableView)
            setupAutoLayout()
        }
    
        func setupAutoLayout() {
    
            tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
            tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
            tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        }
    }
    

    【讨论】:

    • 如果您不需要页眉或页脚,只需删除相应的标记代码并注释 tableView.register 行..
    • 对于选项 2,在 swift 4 中,在 tableView 声明中添加委托和数据源(例如 tv.dataSource = self)会引发错误。相反,我必须在 viewDidLoad 方法中定义 dataSource 和委托。
    • @GeorgeBikas 请使用惰性 var tableView 而不是 let tableView 然后它正在工作......
    【解决方案5】:

    Swift 4兼容

    您应该考虑创建UITableViewController 并避免设置委托,而不是向您的UIViewController 添加UITableView

    class YourTVC: TableViewController {
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
        // setup custom cells if you use them
        tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "yourCell")
      }
    
      // MARK: tableView
      override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3 // set to value needed
      }
    
      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "yourCell", for: indexPath) as! CustomTableViewCell
        cell.textLabel?.text = "Cell at row \(indexPath.row)"
        return cell
      }
    
    }
    

    【讨论】:

      【解决方案6】:

      我遇到了类似的问题,即我的编程 UITableView 不会填充数据。这是因为我使用了没有强引用的委托/数据源。一旦我保留了对它的引用(我有一个实现 UITableViewDataSource 和 UITableViewDelegate 的类),数据就会被填充。

      【讨论】:

        【解决方案7】:
        import UIKit
        
        class ViewController: UITableViewController {
        
        override func viewDidLoad() {
            super.viewDidLoad()
        
            tableView.register(TableCell.self, forCellReuseIdentifier: "cell")
        }
        
        override func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 10
        }
        
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableCell
            cell.nameLabel.text = "TableViewCell programtically"
            cell.nameLabel.textAlignment = .center
            cell.nameLabel.textColor  = .white
            return cell
        }
        
        override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return 100
        }
        }
        

        【讨论】:

          【解决方案8】:

          简单的解决方案

          import UIKit
          
          class CustomTableViewController: UICollectionViewController {
              override func viewDidLoad() {
                  super.viewDidLoad()
                  tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
              }
          
              override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                  return 10
              }
          
              override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                  let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath)
                  cell.textLabel!.text = "\(indexPath.row)"
                  return cell
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-03-28
            • 1970-01-01
            • 2015-02-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多