gpt4 book ai didi

ios - UICollectionView 在 UICollectionViewCells 上调用 setNeedsDisplay

转载 作者:行者123 更新时间:2023-11-28 18:21:14 24 4
gpt4 key购买 nike

我有一个带有自定义 UICollectionViewCell 类的 UICollectionView,我在其中绘制了必要的内容。然而,我发现当我上下滚动 Collection View 时,它会重新绘制每个单元格,因为它会再次滚动并返回到屏幕上。这会导致相当不稳定的滚动。我认为 UICollectionViewCells 是自动缓存和重用的,所以我不明白为什么它会不断重绘它们。

我在自定义 UICollectionViewCell 的 subview 的 setNeedsDisplay 中有一个 NSLog 语句,这就是为什么我知道它正在重绘它们。这是我用于绘制信息的 UICollectionView 代码。 (PFObject 只是使用 Parse 从数据库中检索的对象)

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

if (!cell.mini) {
PFObject *pfMini = [_searchResults objectAtIndex:indexPath.row];
Mini *mini = [Mini instanceWithPFObject:pfMini];
cell.mini = mini;
cell.backgroundColor = [UIColor grayColor];
}
return cell;
}

还有我的自定义单元格。这里的 MiniView 是我创建的用于显示图像的自定义 View ,我在其他各种地方使用它:

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}

- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];

MiniView *miniView = [[MiniView alloc] initWithFrame:rect];
miniView.mini = _mini;
[self addSubview:miniView];

UIImageView *backgroundImage = [[UIImageView alloc] initWithImage:[self randomBackground]];
self.backgroundView = backgroundImage;
}

- (UIImage *)randomBackground
{
int backgroundInt = arc4random()%26 + 8;
UIImage *background = [UIImage imageNamed:[NSString stringWithFormat:@"MainBackground%i", backgroundInt]];
return background;
}

最佳答案

您应该将初始化语句放在 initWithFrame: 方法中。

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
MiniView *miniView = [[MiniView alloc] initWithFrame:rect];
miniView.mini = _mini;
[self addSubview:miniView];

UIImageView *backgroundImage = [[UIImageView alloc] initWithImage:[self randomBackground]];
self.backgroundView = backgroundImage;
}
return self;
}

我不记得在没有实际绘制内容的情况下在 drawRect: 方法中完成了初始化。如果您想实际绘制单元格的内容,您应该使用图形上下文:

UIGraphicsBeginImageContext(self.bounds.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *imageOfContextSnapshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

这将获取当前上下文的“快照”。您可以将其视为将对象粘贴到 Canvas 上。在您的 drawRect: 方法中调用它应该绘制您的内容。请注意,您应该只更新 drawRect: 方法中的上下文,否则您将收到错误消息。此外,只有在实际调用绘图方法时才使用 drawRect: 方法。当创建一个新的 UIView 类时,drawRect: 方法甚至声明只有在绘制内容时才应使用该方法。

有关更多信息,请查看 Apple 的引用资料。他们对图形上下文及其使用方法进行了非常详尽的解释。

https://developer.apple.com/library/mac/documentation/graphicsimaging/conceptual/drawingwithquartz2d/dq_context/dq_context.html

编辑 1:

根据单元格的数量,您可能需要考虑不绘制任何内容。 dequeueReusableCellWithIdentifier 已经回收单元格内容并且做得很好。您应该根据需要同时增加复杂性。虽然这对我来说很容易说,因为我不知道 MiniView 在做什么。

此外,如果您想要更好的性能,您可能需要考虑特定于对象的绘制方法,而不是使用 renderInContext:。例如,NSSString 有:

-drawAtPoint:forWidth:withFont:
-drawAtPoint:forWidth:withFont:

与渲染整个上下文相比,这些在绘制文本方面表现更好。要绘制图像,您应该调用:

-drawInRect:

这些必须在图形上下文中调用,在您的情况下是在 drawRect: 方法中。

编辑 2:

在init方法中初始化时不绘制mini,因为当你调用

PFObject *pfMini = [_searchResults objectAtIndex:indexPath.row];
Mini *mini = [Mini instanceWithPFObject:pfMini];
cell.mini = mini;
cell.backgroundColor = [UIColor grayColor];

在您的 View Controller 中,迷你 View 已被初始化并作为 subview 添加到单元格中,但是当分配迷你 View 的迷你 iVar 时,单元格的迷你 iVar 很可能为 nil。换句话说,当您在 initWithFrame:(CGRect)frame 方法中调用它时:

MiniView *miniView = [[MiniView alloc] initWithFrame:rect];
miniView.mini = _mini;
[self addSubview:miniView];

此时“_mini”为零。在您的 cellForItemAtIndexPath: 方法中,您将分配单元格的 mini,而不是 MiniView 的 mini,因此 MiniView 的 mini 继续为 nil。您可以在 cellForItemAtIndexPath: 中分配 MiniView 的 mini,而不是单元格的 mini,这应该可以解决它。

关于ios - UICollectionView 在 UICollectionViewCells 上调用 setNeedsDisplay,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20349253/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com