【问题标题】:Setting a UITableView data source and delegate in separate file - swift在单独的文件中设置 UITableView 数据源和委托 - swift
【发布时间】:2016-02-29 06:30:05
【问题描述】:

如果我想让相同的基本 UITableView 出现在两个不同的场景中,是否为两个表使用一个数据源和委托位置是个好主意?

我想试试这个,但是当我在 IB 中选择表格视图并尝试将线拖到 UITableView 文件的自定义类,甚至到另一个自定义视图控制器时,它不会连接。似乎只能将当前的 View Controller 变成表的数据源和委托(?)。

我想知道这是否至少类似于this question,但即使是,如何快速完成(也许有一种新方法可以做到这一点)。

【问题讨论】:

    标签: ios swift uitableview delegates datasource


    【解决方案1】:

    每个 Tableview 都应该有自己的 Tableview 控制器。这符合模型视图控制器设计模式。

    如果两个表中的数据相同,则可以有一个公共类作为数据源。

    【讨论】:

      【解决方案2】:

      您可以实现自定义类对象,并为此类实现UITableViewDataSource 方法。

      @interface MyDataSource : NSObject <UITableViewDataSource>
      
      //...
      
      @end
      

      然后,UITableView 具有属性delegatedataSource。 将正确的对象分配给这些属性。

      MyDataSource ds = ... ///< Initialize the dataSource object.
      self.tableView.dataSource = ds; ///< Let ds be the dataSource of `self.tableView`
      self.tableView.delegate = .... ///< Assign the delegate, generally it is `self`.
      

      【讨论】:

      • 虽然这并不快,而且您没有提到创建 tableView 插座,但它已经足够清楚了。您真的需要 self.tableView.dataSource 还是 viewDIdLoad 中的 tableView.dataSource 足够?
      • 我不知道怎么写swift。但我认为它们是相同的。
      • 自定义类:class MyDataSource: NSObject {} Outlet(在故事板和视图控制器中的代码之间链接):@IBOutlet weak var tableView: UITableView ... 在同一个 VC 中,实例化一个 MyDataSource 类型的变量 myDataSource并将 tableView.dataSource 分配给 myDataSource:tableView.dataSource = myDataSource
      【解决方案3】:

      这是一个代码示例,显示了 UITableView 的不同数据源和委托。

      Swift 中的代码

      import UIKit
      
      // MARK: Cell
      
      class ItemCell: UITableViewCell{
          var label: UILabel!
          override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
              super.init(style: style, reuseIdentifier: reuseIdentifier)
              label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 20))
              label.textColor = .black
              label.backgroundColor = .yellow
              contentView.addSubview(label)
          }
      
          required init?(coder aDecoder: NSCoder) {
              fatalError("init(coder:) has not been implemented")
          }
      }
      
      // MARK: Main View Controller
      
      class BlueViewController: UIViewController{
      
          var tableView: UITableView!
          var myDataSourse: MyTVDataSource!
          var myDelegate: MyTVDelegate!
      
      
          override func viewDidLoad() {
              super.viewDidLoad()
              self.view.backgroundColor = .blue
              tableView = UITableView()
              myDataSourse = MyTVDataSource(tableView: tableView)
              myDelegate = MyTVDelegate()
              myDelegate.presentingController = self
              tableView.dataSource = myDataSourse
              tableView.delegate = myDelegate
              tableView.register(ItemCell.self, forCellReuseIdentifier: "Cell")
      
              self.view.addSubview(tableView)
      
      
      
              self.tableView.translatesAutoresizingMaskIntoConstraints = false
      
              NSLayoutConstraint.activate([
                  tableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0),
                  tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0),
                  tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0),
                  tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0)
                  ])
          }
      }
      extension BlueViewController: BluePresenting{
          func currentSelected(_ indexPath: IndexPath) {
              print(indexPath)
          }
      
      
      }
      
      // MARK: TableViewDelegate
      
      
      protocol BluePresenting: class {
          func currentSelected(_ indexPath: IndexPath)
      }
      
      class MyTVDelegate: NSObject,UITableViewDelegate{
      
         var presentingController: BluePresenting?
      
          func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
                  presentingController?.currentSelected(indexPath)
          }
      }
      
      // MARK: TableView DataSource
      
      
      class MyTVDataSource: NSObject, UITableViewDataSource{
          private var tableView: UITableView
          private var items = ["Item 1","item 2","item 3","Item 4"]
      
          init(tableView: UITableView) {
              self.tableView = tableView
          }
          func numberOfSections(in tableView: UITableView) -> Int {
              return 1
          }
          func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
              return items.count
      
          }
          func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
              let cell = ItemCell(style: .default, reuseIdentifier: "Cell")
              cell.label.text = items[indexPath.row]
      
              return cell
          }
      
      }
      

      【讨论】:

      • 请注意,对于任何试图在 obj-c 中重新创建它的人来说,在头文件中包含 @property (nonatomic, strong) id&lt;MyTVDelegate&gt; delegate; 之类的内容是关键(请注意,该属性必须是强大的)
      【解决方案4】:

      斯威夫特 4.1。您可以创建从 UITableViewDataSource 和 UITableViewDelegate 类继承的单独类。这里我在 DataSource 类中实现 UITableViewDataSource() 方法。你需要继承 NSObject 这样我们就不必摆弄 @objc@class 关键字,因为 UITableViewDataSource 是一个 Objective-C 协议

      import Foundation
      import UIKit
      
      class DataSource: NSObject, UITableViewDataSource {
        var formData: [FormData]? = nil
      
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
          return self.formData?.count ?? 0
        }
      
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
          let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
          let label = cell?.contentView.viewWithTag(100) as? UILabel
          let type = self.formData![indexPath.row]
          label?.text = type.placeHolder
          return cell!
        }
      }
      

      现在我们将 DataSource 设置为 UITableView。如果我们创建单独的类,那么我们必须将数据传递给 DataSource 类。

       class ViewController: UIViewController {
      
            @IBOutlet weak var tblView: UITableView!
            var formData: [FormData]? = nil
            var dataSource = DataSource()
      
             override func viewDidLoad() {
                super.viewDidLoad()
                formData = FormData.array
                dataSource.formData = formData // Pass data to DataSource class
                tblView.dataSource = dataSource // Setting DataSource
            }
          }
      

      以类似的方式,您可以在单独的类中实现 UITableViewDelegate。另一种分离 DataSource 和 Delegate 的方法是创建 viewController 的扩展。即使你可以创建单独的类,你只能为你的视图控制器定义扩展。在您定义扩展时,您不需要传递数据。

      class ViewController: UIViewController {
      
        @IBOutlet weak var tblView: UITableView!
        var formData: [FormData]? = nil
      
        override func viewDidLoad() {
          super.viewDidLoad()
          formData = FormData.array
          tblView.dataSource = self
        }
      }
      
      extension ViewController:  UITableViewDataSource {
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
          return self.formData?.count ?? 0
        }
      
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
          let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
          let label = cell?.contentView.viewWithTag(100) as? UILabel
          let type = self.formData![indexPath.row]
          label?.text = type.placeHolder
          label?.backgroundColor = UIColor.gray
          return cell!
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-07-01
        • 2015-11-05
        • 2015-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-10
        相关资源
        最近更新 更多