将数据源分隔到Swift中的另一个类

我试图保持我的视图控制器干净,如本文所述objc.io问题#1更轻的视图控制器 。 我在Objective-C中testing了这个方法,它工作正常。 我有一个单独的类实现UITableViewDataSource方法。

 #import "TableDataSource.h" @interface TableDataSource() @property (nonatomic, strong) NSArray *items; @property (nonatomic, strong) NSString *cellIdentifier; @end @implementation TableDataSource - (id)initWithItems:(NSArray *)items cellIdentifier:(NSString *)cellIdentifier { self = [super init]; if (self) { self.items = items; self.cellIdentifier = cellIdentifier; } return self; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.items.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier forIndexPath:indexPath]; cell.textLabel.text = self.items[indexPath.row]; return cell; } @end 

从tableview控制器,我所要做的就是实例化这个类的一个实例,并将其设置为tableview的数据源,它完美的工作。

 self.dataSource = [[TableDataSource alloc] initWithItems:@[@"One", @"Two", @"Three"] cellIdentifier:@"Cell"]; self.tableView.dataSource = self.dataSource; 

现在我正试图在Swift中做同样的事情。 首先这是我的代码。 它几乎是上面的Objective-C代码的翻译。

 import Foundation import UIKit public class TableDataSource: NSObject, UITableViewDataSource { var items: [AnyObject] var cellIdentifier: String init(items: [AnyObject]!, cellIdentifier: String!) { self.items = items self.cellIdentifier = cellIdentifier super.init() } public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return items.count } public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as UITableViewCell cell.textLabel?.text = items[indexPath.row] as? String return cell } } 

我这样称呼它。

 let dataSource = TableDataSource(items: ["One", "Two", "Three"], cellIdentifier: "Cell") tableView.dataSource = dataSource 

但该应用程序崩溃与以下错误。

– [NSConcreteNotification tableView:numberOfRowsInSection:]:无法识别的select器发送到实例

我检查了TableDataSourceinit方法,项目和单元格标识符通过罚款。 我不得不public声明UITableViewDataSource方法,并删除override关键字,否则会给编译时间错误。

我对这里出了什么问题毫无头绪。 任何人都可以帮我吗?

谢谢。

为数据源创build一个属性,并将其与您的tableview一起使用。

 class ViewController: UIViewController { @IBOutlet weak var tableView: UITableView! var dataSource:TableDataSource! override func viewDidLoad() { super.viewDidLoad() dataSource = TableDataSource(items: ["One", "Two", "Three"], cellIdentifier: "Cell") tableView.dataSource = dataSource } } 

我用下面的代码,为更通用的方法,作为一个尝试..

 import UIKit class CustomDataSource<ItemsType, CellType:UITableViewCell>: NSObject, UITableViewDataSource { typealias ConfigureCellClosure = (_ item: ItemsType, _ cell: CellType) -> Void private var items: [ItemsType] private let identifier: String private var configureCellClosure: ConfigureCellClosure init(withData items: [ItemsType], andId identifier: String, withConfigBlock config:@escaping ConfigureCellClosure) { self.identifier = identifier self.items = items self.configureCellClosure = config } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return items.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: self.identifier, for: indexPath) as! CellType configureCellClosure(items[indexPath.row], cell) return cell } func item(at indexpath: IndexPath) -> ItemsType { return items[indexpath.row] } } 

在视图控制器

  var dataSource: CustomDataSource<CellObject, CustomTableViewCell>? override func viewDidLoad() { super.viewDidLoad() dataSource = CustomDataSource<CellObject, CustomTableViewCell>(withData: customDataStore.customData(), andId: CustomTableViewCell.defaultReuseIdentifier) { (cellObject, cell) in cell.configureCell(with: cellObject) } customTableView.dataSource = dataSource // Do any additional setup after loading the view. } 

在我的小项目WorldCountriesSwift中使用这种方法

扩大“ayalcinkaya”接受的答案,这解释了如何,但不是为什么

最可能发生的事情是你的TableDataSource被解除分配,因为tableview.dataSource是一个弱引用 ,这就是为什么创build一个属性解决了问题,因为它创build一个强大的引用,并避免dataSource委托被释放。