在单独的文件中设置 UITableView 数据源和委托 - swift
Setting a UITableView data source and delegate in separate file - swift
如果我想让相同的基本 UITableView 出现在两个不同的场景中,对两个 table 都使用一个数据源和委托位置是个好主意吗?
我想试试这个,但是当我 select IB 中的 table 视图并尝试将行拖到自定义 class 的 UITableView 文件,甚至拖到另一个自定义视图控制器,它不会连接。似乎只能将当前的视图控制器变成 table 的数据源和委托(?)。
我想知道这是否至少类似于 this question,但即使是,在 swift 中是如何完成的(也许有一种新方法可以做到这一点) .
每个 Tableview 都应该有自己的 Tableview 控制器。这符合模型视图控制器设计模式。
如果两个表中的数据相同,可以有一个共同的class作为dataSource。
您可以实现自定义 class 对象,并为此 class 实现 UITableViewDataSource
方法。
@interface MyDataSource : NSObject <UITableViewDataSource>
//...
@end
然后,UITableView
具有属性 delegate
和 dataSource
。
为这些属性分配正确的对象。
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`.
这是一个代码示例,显示了 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
}
}
Swift 4.1。您可以创建单独的 class,它将继承自 UITableViewDataSource 和 UITableViewDelegate class。这里我在 DataSource class 中实现 UITableViewDataSource() 方法。您需要继承 NSObject 这样我们就不必 fiddle 与 @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。如果我们单独创建 class 那么我们必须将数据传递给 DataSource class.
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
}
}
以类似的方式,您可以在单独的 class 中实现 UITableViewDelegate。另一种分离 DataSource 和 Delegate 的方法是创建 viewController 的扩展。甚至你可以创建单独的 class ,你只能在其中为你的视图控制器定义扩展。在你定义扩展中,你不需要传递数据。
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 出现在两个不同的场景中,对两个 table 都使用一个数据源和委托位置是个好主意吗?
我想试试这个,但是当我 select IB 中的 table 视图并尝试将行拖到自定义 class 的 UITableView 文件,甚至拖到另一个自定义视图控制器,它不会连接。似乎只能将当前的视图控制器变成 table 的数据源和委托(?)。
我想知道这是否至少类似于 this question,但即使是,在 swift 中是如何完成的(也许有一种新方法可以做到这一点) .
每个 Tableview 都应该有自己的 Tableview 控制器。这符合模型视图控制器设计模式。
如果两个表中的数据相同,可以有一个共同的class作为dataSource。
您可以实现自定义 class 对象,并为此 class 实现 UITableViewDataSource
方法。
@interface MyDataSource : NSObject <UITableViewDataSource>
//...
@end
然后,UITableView
具有属性 delegate
和 dataSource
。
为这些属性分配正确的对象。
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`.
这是一个代码示例,显示了 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
}
}
Swift 4.1。您可以创建单独的 class,它将继承自 UITableViewDataSource 和 UITableViewDelegate class。这里我在 DataSource class 中实现 UITableViewDataSource() 方法。您需要继承 NSObject 这样我们就不必 fiddle 与 @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。如果我们单独创建 class 那么我们必须将数据传递给 DataSource class.
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
}
}
以类似的方式,您可以在单独的 class 中实现 UITableViewDelegate。另一种分离 DataSource 和 Delegate 的方法是创建 viewController 的扩展。甚至你可以创建单独的 class ,你只能在其中为你的视图控制器定义扩展。在你定义扩展中,你不需要传递数据。
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!
}
}