iOS、UICollectionViewCell 格式错误的 UILabel

iOS, UICollectionViewCell malformed UILabel

我有一个显示电话号码块的 UICollectionViewController(见图)。当视图加载时,它们看起来都很好,但是当我开始滚动、更改旋转或执行更改数据来源的(可变)数组的搜索功能时,我看到这些格式错误的标签。我确实认为它可能是 iOS 模拟器,但是从它的角度来看,它似乎是 UICollectionViewCells 的定位问题。

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *identifier = @"cell";
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];

    cell.backgroundColor = [UIColor grayColor];
    cell.layer.cornerRadius = 5;
    [cell setClipsToBounds: YES];

    CGRect cellBound = CGRectMake(25, 12.5, 150, 12.5); // x, y, w, h
    UILabel *title = [[UILabel alloc] initWithFrame:cellBound];

    NSString *number = [[searchNumbers objectAtIndex:indexPath.row] valueForKey:@"number"];
    number = [number stringByReplacingOccurrencesOfString:@"+44" withString: @"0"];
    title.text = number;

    [cell addSubview:title];
    return cell;
}

需要注意的是我使用的是UICollectionViewFlowLayout

我相信这是因为您正在向您的单元格中添加越来越多的 UILabel 子视图(在调用 cellForItemAtIndexPath 时一遍又一遍)。您需要添加一个检查,并且 如果单元格还没有 ,则只添加一个标签子视图。 出列的单元格如果被重复使用,则已经具有标签子视图,如果该标签已经存在,您只需从数据源中设置它的文本。

伪代码:

for subview in subviews {
    if subview.isKindOfClass(UILabel) {
        // assign the new text label.
    }
    else
    {
       // create and add the UILabel subView.
    }

}

这是一个容易犯的错误,因为 dequeueReusableCellWithReuseIdentifier 可以为您提供以前使用过的单元格,或者如您所见,最初为您提供一个新单元格。这就是为什么该应用程序在您启动时运行正常,但在您滚动时变得混乱的原因。

正如@Woodstock 提到的,这是由于 "over-adding" UILabel 对您的单元格的反对。

而不是他的解决方案,它仍然将 UILabel 添加到 -collectionView:cellForRowAtIndexPath: 中的单元格,更好的 MVC 解决方案是:

// A UICollectionViewCell subclass
// Make sure to pick the correct "init" function for your use case
- (instancetype)init... {
    self = [super init...];
    if (self != nil) {
        [self setupCell];
    }
    return self;
}
- (void)setupCell {
    self.backgroundColor    = [UIColor grayColor];
    self.clipsToBounds      = YES;
    self.layer.cornerRadius = 5;
    CGRect cellBound        = CGRectMake(25, 12.5, 150, 12.5); // x, y, w, h
    // Assumes you've set up a UILabel property
    self.titleLabel         = [[UILabel alloc] initWithFrame:cellBound];
    [cell addSubview:self.titleLabel];
}
- (void)configureWithNumber:(NSString *)number {
    number                  = [number stringByReplacingOccurrencesOfString:@"+44" withString: @"0"];
    self.titleLabel.text    = number;
}

// In your UICollectionViewDataSource/Delegate implementation
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *identifier = @"cell";
    UICollectionViewCell *cell  = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
    NSString *number            = [[searchNumbers objectAtIndex:indexPath.row] valueForKey:@"number"];
    [cell configureWithNumber:number];
    return cell;
}

基本上,您只想在最初设置单元格时设置和添加视图。之后,您应该传入数据 value/object 和 configure 单元格。如果您有需要不同控件的单元格(2 个标签与 1 个标签等),则制作多个 sub类。这样,您封装了 类 以获得更清晰的代码和更好的重用。