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类。这样,您封装了 类 以获得更清晰的代码和更好的重用。
我有一个显示电话号码块的 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类。这样,您封装了 类 以获得更清晰的代码和更好的重用。