CollectionViewをスクロールすると表示が崩れる

投稿者: Anonymous

現在CollectionViewに0〜299までの数字を持ったセルがあり、1という数字が表示されているセルの横にラインを引いたのですが、
下にスクロールしていくと関係のない107や222といった数字のセルにラインが引かれて表示されてしまいます。何度も何度もスクロールをしていくとどんどんラインが増殖していきます。cellForItemAtIndexPathにおけるセルの再利用方法に問題があるのでしょうか?
また、cellForItemAtIndexPath内で毎回BoundaryLineSideのインスタンスを生成していることが原因かと思いViewDidLoadで一回だけ生成してラインを描画させるようにしたのですが、これでも1とは関係のない数字のセルにラインが引かれました。
下記のコードのどこに問題があるのでしょうか?
どなたか分かる方がいれば教えていただきたいです。すみませんが、よろしくお願いします。

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView
     numberOfItemsInSection:(NSInteger)section
{
    return 300;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    NumberCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"Cell"
                                                                                forIndexPath:indexPath];
    cell.number.text = [NSString stringWithFormat:@"%ld", (long)indexPath.row];

    if ([cell.number.text isEqual: @"1"]) {
        BoundaryLineSide *boundarySide = [[BoundaryLineSide alloc] initWithFrame:cell.bounds];
        [cell addSubview:boundarySide];
    }

    return cell;
}



@implementation BoundaryLineSide

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    CGRect bounds_ = rect;
    CALayer *border = [CALayer layer];
    border.frame = CGRectMake(0, 0.0f, 2.0f, bounds_.size.height);
    border.backgroundColor = [UIColor blueColor].CGColor;
    [self.layer addSublayer:border];
}

解決

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    NumberCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"Cell"
                                                                      forIndexPath:indexPath];
    cell.number.text = [NSString stringWithFormat:@"%ld", (long)indexPath.row];

    if ([cell.number.text isEqual: @"1"]) {
        BoundaryLineSide *boundarySide = [[BoundaryLineSide alloc] initWithFrame:cell.bounds];
        [cell addSubview:boundarySide];

いちどaddSubview:したら、そのセルが再利用されたときにも、boundarySideは、セルに貼り付けられたままです。セルのテキストが"1"ではなく、かつセルのsubviewsboundarySideが含まれているとしたら、boundarySideremoveFromSuperviewしなければいけません。
(私なら、addSubview:removeFromSuperviewをくり返すのは、ハードウェアにとってもめんどくさいことなので、セルには固定でラインを貼り付けたままにしておいて、ラインのhidden属性をコントロールすることを考えます。)

    }

    return cell;
}
回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *