旋转 UITableView 时更新 UITableViewCells 时出现问题

发布于 2024-09-18 03:22:53 字数 1160 浏览 4 评论 0原文

我在自定义 UITableViewCell 中有一个 UILabel,当设备旋转时它会调整大小。旋转后需要重新计算此标签中的文本,因为我正在将其缩小到大小并在末尾附加一些文本。

例如,数据模型有:“这是一个需要停止的连续句子。”

在纵向模式下,它变成“这是一个连续发送...更多”

在横向模式下,它变成“这是一个连续句子...更多”

来自 (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 我能够访问可见的 UITableViewCells 并更新描述。

问题似乎是有 UITableViewCells 被缓存但我无法访问。当我在旋转后滚动 UITableView 时,旋转后可见区域下方的一两个单元格的标签中没有正确的文本。因此,它们尚未通过 (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 渲染 - 但它们不是由 [tableViewvisibleCells] 返回(或通过循环通过 [tableView subViews] 返回的所有视图)。

我尝试通过此方法访问“额外”单元格:(

for (int index=max + 1; index < max + 3 && index < [cellTypes count]; index++) {
    NSIndexPath *updatedPath = [NSIndexPath indexPathForRow:index inSection:0];
    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:updatedPath];
    if (cell == nil) { continue; }
    [self updateCellForRotate:cell forRow:index];
}

其中 max 是从visibleCells 返回的最大行)但单元格始终为零。

是否有办法刷新 UITableViewCells 的缓存,以便它们不会被重复使用?或者访问它们以便我可以更新它们?

谢谢!

I have a UILabel in a custom UITableViewCell that gets resized when the device is rotated. The text in this label needs to be recalculated after the rotation because I am cutting it down to size and appending some text at the end.

E.g. the datamodel has: "This is a run-on sentence that needs to stop."

In portrait mode it becomes "This is a run-on sent... more"

In landscape mode it becomes "This is a run-on sentence that... more"

From (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
I am able to access the visible UITableViewCells and update the descriptions.

The problem seems to be that there are UITableViewCells that are cached but I can't get to. When I scroll the UITableView after a rotation, one or two cells that are below the visible area after the rotation don't have the correct text in the label. So they haven't been rendered via (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath - but they weren't returned by [tableView visibleCells] (or via looping through all views returned via [tableView subViews]).

I've tried to access the "extra" cells via this method:

for (int index=max + 1; index < max + 3 && index < [cellTypes count]; index++) {
    NSIndexPath *updatedPath = [NSIndexPath indexPathForRow:index inSection:0];
    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:updatedPath];
    if (cell == nil) { continue; }
    [self updateCellForRotate:cell forRow:index];
}

(where max is the biggest row returned from visibleCells) but cell is always nil.

Is there anyway to flush the cache of UITableViewCells so that they don't get re-used? Or to access them so I can update them?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

赠佳期 2024-09-25 03:22:53

有两件事。
第一的。在您的 didRotateFromInterfaceOrientation 方法中,您可以简单地重新加载可见行,如下所示:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation) fromInterfaceOrientation
{
    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];

    NSLog(@"didRotateFromInterfaceOrientation:%d",fromInterfaceOrientation);
    [tableView reloadRowsAtIndexPaths:[tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];
}

然后我建议您将 interfaceOrientation 数字或简单的表宽度添加到出列单元格名称中tableView 知道一次旋转中的单元格与另一轮中的单元格不同。就像这样:

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath withType:(NSString *)s_type
{
    UITableViewCell *cell = nil;
    // add width of table to the name so that rotations will change the cell dequeue names
    s_cell = [s_cell stringByAppendingString:[NSString stringWithFormat:@"%@%d",@"Width",(int)tv.bounds.size.width]];

    NSLog(@"%@",s_cell);
    cell = [tv dequeueReusableCellWithIdentifier:s_cell];
    if( cell == nil ) { 
        cell = [[[UITableViewCell alloc];
        initWithFrame:CGRectZero reuseIdentifier:s_cell] autorelease];
    }
}

Two things.
First. In your didRotateFromInterfaceOrientation method you can simply reload the visible rows like so:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation) fromInterfaceOrientation
{
    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];

    NSLog(@"didRotateFromInterfaceOrientation:%d",fromInterfaceOrientation);
    [tableView reloadRowsAtIndexPaths:[tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];
}

Then I would recommend you add either the interfaceOrientation number or simply the table width to the dequeue cell name that way the tableView knows that cells in one rotation are different from those in another. Like so:

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath withType:(NSString *)s_type
{
    UITableViewCell *cell = nil;
    // add width of table to the name so that rotations will change the cell dequeue names
    s_cell = [s_cell stringByAppendingString:[NSString stringWithFormat:@"%@%d",@"Width",(int)tv.bounds.size.width]];

    NSLog(@"%@",s_cell);
    cell = [tv dequeueReusableCellWithIdentifier:s_cell];
    if( cell == nil ) { 
        cell = [[[UITableViewCell alloc];
        initWithFrame:CGRectZero reuseIdentifier:s_cell] autorelease];
    }
}
零度° 2024-09-25 03:22:53

首先,要重新加载所有表格单元格,请使用 [self.tableView reloadData]

其次,添加负责在 (UITableViewCell *)tableView:(UITableView * 内缩小的代码行)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 方法。

示例:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    //Some identifier and recycling stuff

    if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
        //Make labels smaller
    }
    else {
        //Make them bigger
    }
}

或者您可以在制作它们时调用 updateCellForRotate:forRow: 方法。但我不确定该功能是如何工作的,所以我不能太具体。

Firstly, to reload all of your table cells use [self.tableView reloadData]

Secondly, add the line of code that is responsible for the shrinking inside the (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method.

Example:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    //Some identifier and recycling stuff

    if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
        //Make labels smaller
    }
    else {
        //Make them bigger
    }
}

Or you can just call your updateCellForRotate:forRow: method when making them. But I'm not sure how that function works, so I can't be too specific.

樱娆 2024-09-25 03:22:53

当您在 cellForRowAtIndexPath: 中创建单元格时,将其添加到数组中。然后,循环遍历数组,根据需要更新文本。

希望这有帮助,
jrtc27

编辑:

你说它们是自定义单元格 - 你不能更新 UITableViewCell 子类中的文本吗?

When you create the cell in cellForRowAtIndexPath:, add it to an array. Then, loop through the array, updating the text as necessary.

Hope this helps,
jrtc27

EDIT:

You say they are custom cells - could you not update your text in your UITableViewCell subclass?

So要识趣 2024-09-25 03:22:53

所以,我最近遇到了(我认为是)一个非常相似的问题,很抱歉,发布的答案都没有帮助我。

我的问题是我故意在旋转时调整 UITableView 的大小和位置,并且我以编程方式做到了这一点。纵向模式下的表格单元格占据了视图的宽度,而横向模式下的表格单元格则稍高但宽度较小。然后,我根据我们所处的方向重新定位单元的元素。

应用程序启动后,第一次查看表格效果很好。然后我旋转,发现我似乎有一些元素的两个实例,这些似乎是第一个表中单元格可见的位置。然后旋转回来,用前一个表中的元素破坏了初始方向表。

我尝试了上面所有适用的答案,直到我仔细查看了 cellForRowAtIndexPath 代码:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}

我知道单元格重用是一个好主意,但我真的不需要保留(如保留)任何单元格并想要它们每次旋转后一切都明亮、闪亮、焕然一新。

编辑:在我自己的应用程序中,我最多可能有 20-30 行,因为我个人不喜欢太长的表格。如果某个特定查询返回大量行,我将为用户提供一些过滤器来帮助他们筛选出他们想要的行。如果您要显示大量行,那么将它们出列可能会导致您不希望的性能影响。

我所做的就是注释掉 if 和下面的括号,我的表格单元格完全按照我想要的方式更新:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//}

对华夫饼的歉意,以及对一个老问题的迟到回答。

本.

华夫饼和奶油或糖浆。

So, I was having (what I think was) a very similar problem recently, and none of the posted answers helped me, I'm sorry to say.

My issue was that I deliberately resized and repositioned the UITableView upon rotation, and I did that programatically. The table cells in portrait took up the width of the view, and in Landscape were made somewhat higher but less wide. I then repositioned the elements of the cell depending on the orientation we'd come to.

Upon application start, the first viewing of the table was fine. Then I rotated and found that I appeared to have two instances of some elements, and these appeared to be where the cells had been visible in the first table. Rotating back then corrupted the initial orientation table with elements from the previous table.

I tried all of the applicable answers above, until I looked closer at the cellForRowAtIndexPath code:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}

I understand cell re-use is a great idea and all, but I really didn't need to retain (as in preserve) any cells and wanted them all bright, spangly and new after each rotation.

EDIT: In my own app I'll have maybe 20-30 rows maximum, as I personally don't like hugely long tables. If there were going to be lots of rows returned for a particular query I'd have some filters available to the user to help them sort out which rows they wanted. If you're going to have loads of rows displayed, then dequeuing them may cause you a performance impact that you don't want.

All I did was comment out the if and the following bracket, and my table cells renewed exactly as I wanted them to:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//}

Apologies for the waffle, and the late answer to an old question.

Ben.

Waffles and cream, or syrup.

酒儿 2024-09-25 03:22:53

您可以在 shouldAutorotateToInterfaceOrientation 方法上使用这个简单的行:

self.view.autoresizesSubviews = YES;

对我来说,它总是成功

You can use this simple line on the shouldAutorotateToInterfaceOrientation method :

self.view.autoresizesSubviews = YES;

For me it works always successfully

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文