在单独的文件中设置 UITableView 数据源和委托 - swift

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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!
  

【讨论】:

以上是关于在单独的文件中设置 UITableView 数据源和委托 - swift的主要内容,如果未能解决你的问题,请参考以下文章

如何在 .xib 文件上创建的 UIViewController 中设置 UITableView

如何在 UITableView 中设置动态单元格分隔线? [复制]

在自定义 UIview 中设置 UItableview 的委托和数据源

如何在 UITableView 中设置 UILabel 的动作

在自定义 uitableviewcell 中设置图像会导致延迟

如何在 UITableView 中设置单元格高度?