この記事 objc.io Issue#1 Lighter View Controllers で説明されているように、ビューコントローラをクリーンな状態に保ちます。私はこの方法をObjective-Cでテストしましたが、うまく機能します。 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
テーブルビューコントローラーから、このクラスのインスタンスをインスタンス化し、テーブルビューのデータソースとして設定するだけで、完全に機能します。
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:]:認識されないセレクターがインスタンスに送信されました
init
のTableDataSource
メソッドを確認したところ、アイテムとセル識別子が正常に渡されました。 UITableViewDataSource
メソッドpublic
を宣言し、override
キーワードを削除する必要がありました。そうしないと、コンパイル時にエラーが発生します。
私はここで何が悪いのか見当がつかない。誰か私を助けてくれますか?
ありがとうございました。
データソースのプロパティを作成し、それをテーブルビューで使用します。
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」で拡張します。これは、howを説明しますが、whyは説明しません。
おそらく何が起こっているのかというと、TableDataSourceが tableview.dataSourceは弱参照 として割り当て解除されているため、プロパティを作成すると、強い参照が作成され、dataSourceデリゲートが回避されるため、問題が解決します。割り当て解除。