3

UITableViewDatasource のクラス クラスターを作成しようとしています。私のインターフェースは次のようになります。

@interface ArrayDataSource : NSObject <UITableViewDataSource>
- (id)initWithItems:(NSArray *)items cellIdentifier:(NSString *)cellIdentifier configureCellBlock:(TableViewCellConfigureBlock)configurationBlock;
- (id)initWith2DArray:(NSArray *)array sectionIdentifiers:(NSArray *)cellIdentifiers configureCellBlock:(TableViewCellConfigureBlock)configurationBlock;
- (id)itemAtIndexPath:(NSIndexPath *)indexPath;
@end

内部的には、抽象クラスは次のようになります。

@implementation ArrayDataSource

- (id)initWithItems:(NSArray *)items cellIdentifier:(NSString *)cellIdentifier configureCellBlock:(TableViewCellConfigureBlock)configurationBlock {
    return [[SingleArrayDatasource alloc] initWithItems:items cellIdentifier:cellIdentifier configureCellBlock:configurationBlock];
}

- (id)initWith2DArray:(NSArray *)array sectionIdentifiers:(NSArray *)cellIdentifiers configureCellBlock:(TableViewCellConfigureBlock)configurationBlock {
    return [[TwoDimensionalArrayDatasource alloc] initWith2DArray:array sectionIdentifiers:cellIdentifiers configureCellBlock:configurationBlock];
}

さて、抽象クラス(ArrayDatasource)がuitableviewデータソースに必要なメソッドを実装していないと不平を言っているコンパイラを沈黙させるために、これらを追加しました:

#pragma mark - Overrides
- (id)itemAtIndexPath:(NSIndexPath *)indexPath { return nil; }
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 0; }
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 0; }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { return nil; }

しかし、クラスターを使用するときはいつでも、データソース メソッド呼び出しは抽象クラスに行きます! これらのオーバーライドを削除すると、すべてが希望どおりに機能します (コンパイラの警告がまだ残っている場合を除く)。

何が起こっている?SingleArrayDatasourceインスタンスが aまたは aのときに、これらのメッセージが抽象クラスに送信されるのはなぜTwoDimentionalArrayDatasourceですか?

アップデート

具体的なサブクラスの1つを実装する方法は次のとおりです

@implementation SingleArrayDatasource

- (id)initWithItems:(NSArray *)items cellIdentifier:(NSString *)cellIdentifier configureCellBlock:(TableViewCellConfigureBlock)configurationBlock
{
    self = [super init];
    if (self) {
        self.items              = items;
        self.cellIdentifier     = cellIdentifier;
        self.configureCellBlock = [configurationBlock copy];
    }
    return self;
}

- (id)itemAtIndexPath:(NSIndexPath *)indexPath
{
    return self.items[indexPath.row];
}

#pragma mark UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.items.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    id cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier forIndexPath:indexPath];
    id item = [self itemAtIndexPath:indexPath];
    self.configureCellBlock(cell, item);
    return cell;
}
4

2 に答える 2

0

あなたの問題は、少なくとも Java のように、Objective C が実際には抽象型を持たないために発生しています。

また、インスタンス メソッドである init からモーフィングされた型を返しています。これは、「抽象型」のインスタンスを既に操作している必要があることを意味します。これは非論理的です。

「抽象クラス」でファクトリパターンを使用することをお勧めします-

@implementation ArrayDataSource

+ (id)dataSourceWithItems:(NSArray *)items cellIdentifier:(NSString *)cellIdentifier configureCellBlock:(TableViewCellConfigureBlock)configurationBlock {
    return [[SingleArrayDatasource alloc] initWithItems:items cellIdentifier:cellIdentifier configureCellBlock:configurationBlock];
}

+ (id)dataSourceWith2DArray:(NSArray *)array sectionIdentifiers:(NSArray *)cellIdentifiers configureCellBlock:(TableViewCellConfigureBlock)configurationBlock {
    return [[TwoDimensionalArrayDatasource alloc] initWith2DArray:array sectionIdentifiers:cellIdentifiers configureCellBlock:configurationBlock];
}

これらはクラス メソッドであるため、alloc と init を呼び出すことが有効です。

于 2014-04-23T22:44:55.000 に答える