首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Swift中将数据源分离到另一个类

在Swift中将数据源分离到另一个类
EN

Stack Overflow用户
提问于 2014-09-11 21:30:50
回答 3查看 12.1K关注 0票数 21

正如本文objc.io Issue #1 Lighter View Controllers中所描述的那样,我正在努力保持视图控制器的整洁。我在Objective-C中测试了这个方法,它工作得很好。我有一个实现UITableViewDataSource方法的独立类。

代码语言:javascript
复制
#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的数据源,它可以完美地工作。

代码语言:javascript
复制
self.dataSource = [[TableDataSource alloc] initWithItems:@[@"One", @"Two", @"Three"] cellIdentifier:@"Cell"];
self.tableView.dataSource = self.dataSource;

现在我正尝试在Swift中做同样的事情。首先,这是我的代码。它相当于上面的Objective-C代码的翻译。

代码语言:javascript
复制
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
    }

}

我这样称呼它。

代码语言:javascript
复制
let dataSource = TableDataSource(items: ["One", "Two", "Three"], cellIdentifier: "Cell")
tableView.dataSource = dataSource

但应用程序崩溃,并出现以下错误。

-NSConcreteNotification表sent :numberOfRowsInSection::发送到实例的无法识别的选择器

我检查了TableDataSource和items的init方法,单元格标识符传递得很好。我必须将UITableViewDataSource方法声明为public并删除override关键字,否则会给出编译时错误。

我不知道这里出了什么问题。有谁能帮帮我吗?

谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-02 20:32:03

为数据源创建一个属性,并将其用于您的表视图。

代码语言:javascript
复制
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

  }
}
票数 28
EN

Stack Overflow用户

发布于 2016-11-07 19:16:20

我使用了以下代码,以获得更通用的方法,作为尝试。

代码语言:javascript
复制
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]
    }

}

在视图控制器中

代码语言:javascript
复制
   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中使用了这种方法

票数 6
EN

Stack Overflow用户

发布于 2017-07-19 20:32:40

通过"ayalcinkaya“扩展了被接受的答案,它解释了how,但没有解释为什么

最有可能发生的情况是,您的TableDataSource作为tableview.dataSource is a weak reference被释放,这就是为什么创建一个属性可以解决问题,因为它创建了一个强引用,并避免了dataSource委托被释放。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25788782

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档