1

カスタム UICollectionViewCells を含む UICollectionView があります (TestReceiptCell はクラス名です)。

カスタムセルにUILabelのみが含まれている場合、UICollectionViewを表示してカスタムセルをロードするのに問題はありませんでした。

次に、IB を介して UITableView を TestReceiptCell NIB ファイルに追加しました。UITableView の TestReceiptCell.h に参照アウトレットを設定し、.m ファイルに合成しました。UITableView のデリゲートとデータソースを、UICollectionView を含む ViewController に設定します。

アプリを実行すると、3 行目のこのブロックで EXC_ BAD_ ACCESS 例外が発生します。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *cellIdentifier = @"TestReceiptCell";
    TestReceiptCell *cell = (TestReceiptCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath]; //exception thrown here
    return cell;
}

Zombie Instrument テストを実行したところ、割り当て解除されたメモリ呼び出しがここで発生していることがわかりました。その機器を使用するのはこれが初めてなので、ここから調査する方法が正確にはわかりません。

参考までに、コードの関連部分をいくつか示します。

ViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self.myCollectionView registerNib:[UINib nibWithNibName:@"TestReceiptCell" bundle:nil]  forCellWithReuseIdentifier:@"TestReceiptCell"];

    // Setup flowlayout
    myCollectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
    [myCollectionViewFlowLayout setItemSize:CGSizeMake(310, 410)];
    [myCollectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
    [self.myCollectionView setCollectionViewLayout:myCollectionViewFlowLayout];
    self.myCollectionView.pagingEnabled = YES;
}

ViewController.m ファイルにも UITableView データソースとデリゲート メソッドを実装していますが、EXC_BAD_ACCESS 例外が発生したため、ここに問題があるかどうかはわかりません。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = nil;
    cell = [tableView dequeueReusableCellWithIdentifier:@"eventCell"];

    if(!cell){
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"eventCell"];
    }
    return cell;
}

アップデート:

cellForItemAtIndexPath を次のように変更すると、これを実行できます。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *cellIdentifier = @"TestReceiptCell";
    //TestReceiptCell *cell = (TestReceiptCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
    TestReceiptCell *cell = [NSBundle.mainBundle loadNibNamed:@"TestReceiptCell" owner:self options:nil][0];
    return cell;
}

ただし、セルをデキューしているのではなく、これが正しい方法ではないことはわかっています。dequeueReusableCellWithResueIdentifier が新しいセルを作成するときに呼び出される initWithFrame メソッドのどこかに問題があるようです。現在、その方法は次のとおりです。

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"TestReceiptCell" owner:self options:nil];
        if ([arrayOfViews count] < 1) {
            return nil;
        }
        if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[UICollectionViewCell class]]) {
            return nil;
        }
        self = [arrayOfViews objectAtIndex:0];
    }
    return self;
}

編集:

テーブルビューのデリゲートまたはデータソースを選択しないと、テーブルビューを含むコレクションビューが読み込まれます。デリゲート/データソースをファイルの所有者にアタッチすると、エラーが発生します。

4

1 に答える 1

2

セルを再利用するために UINib を登録すると、 dequeueReusableCellWithReuseIdentifier:forIndexPath: は、登録した UINib で instantiateWithOwner:options: を呼び出すものです。所有者に渡すものは何でも、ペン先のファイルの所有者アウトレットになります。

ファイルの所有者が UICollectionView であることを期待しているようですが、そうではないと思います。

たとえそうであったとしても、各コレクション セルに含まれる UITableView のデリゲートに UICollectionView を使用するべきではないと思います。それには、UICollectionView が各セル内の tableViews とコンテンツを追跡する必要があります。

含まれている tableView のデリゲートをコレクション セル自体に設定し、各セルで独自のテーブルビューを管理することをお勧めします。

編集:

コレクション ビュー セルのデリゲート プロトコルを定義して、関連するテーブル ビュー イベントをコレクション ビューに伝えることができます。このアプローチでは、コレクション ビュー データソースの collectionView:cellForItemAtIndexPath メソッドで、各コレクション セルに対して定義したデリゲート プロパティを設定します。

たとえば、ユーザーがテーブルから項目を選択した場合、セル デリゲートを呼び出して、どの項目が選択されたかをコレクション ビューに通知できます。

このアプローチにより、コレクション セルがテーブル ビューを使用してセル情報を表示しているという事実を抽象化できます。後で、たとえば埋め込みの UICollectionView を使用してこれらの項目を表示することにした場合、デリゲート プロトコルは変更されずに残り、変更をコレクション セルに分離することができます。

于 2013-03-12T23:16:47.597 に答える