简体   繁体   中英

UITableView scrolling issue

I have a TableView with custom cells, some of which have images and others don't have. Everything works fine but when I start scrolling the cells aren't showing correctly (the images are placed in "wrong" cells and cut in the middle). Does anyone now how to fix this?

The key thing to understand is that your table's cells are reused. This is done to increase the performance for scrolling because creating a new cell - which is a view - is quite expensive.

In the method cellForRowAtIndexPath, you return a cell. Either an existing cell using the dequeue method, or you create a new one. On that cell, you set all the properties of whatever it is you wish to represent.

My guess is that you are setting these properties such as image, etc. on the cell directly. Then when you scroll, that cell is reused and you see the same image again but on the wrong cell.

So, what you need is a separate index like an NSArray to maintain your model objects. That model object contains all the details of image, etc.

Let's take an example. I have an array with 10 objects, the first five of which are image "a.png" and the second five "b.png".

If I receive a callback of cellForRowAtIndexPath, I want to do as follows:

cellForRowAtIndexPath:(0,0) provide object from array a index 0, which is a.png cellForRowAtIndexPath:(0,1) provide object from array a index 1, which is a.png cellForRowAtIndexPath:(0,2) provide object from array a index 2, which is a.png cellForRowAtIndexPath:(0,3) provide object from array a index 3, which is a.png cellForRowAtIndexPath:(0,4) provide object from array a index 4, which is a.png cellForRowAtIndexPath:(0,5) provide object from array a index 5, which is b.png cellForRowAtIndexPath:(0,6) provide object from array a index 6, which is b.png cellForRowAtIndexPath:(0,7) provide object from array a index 7, which is b.png cellForRowAtIndexPath:(0,8) provide object from array a index 8, which is b.png cellForRowAtIndexPath:(0,9) provide object from array a index 9, which is b.png

Now, let's consider that in the UITableView, underneath the covers, five of the cells are being reused.

For each call above, the following happens:

cellForRowAtIndexPath:(0,1) provide object from array a index 1, which is a.png -- you attempt to dequeue an existing cell but it comes back "nil" so you create a new cell. You set the details of your model object.

cellForRowAtIndexPath:(0,2) provide object from array a index 2, which is a.png -- you attempt to dequeue an existing cell but it comes back "nil" so you create a new cell. You set the details of your model object.

cellForRowAtIndexPath:(0,3) provide object from array a index 3, which is a.png -- you attempt to dequeue an existing cell but it comes back "nil" so you create a new cell. You set the details of your model object.

cellForRowAtIndexPath:(0,4) provide object from array a index 4, which is a.png -- you attempt to dequeue an existing cell but it comes back "nil" so you create a new cell. You set the details of your model object.

cellForRowAtIndexPath:(0,5) provide object from array a index 5, which is b.png -- you attempt to dequeue an existing cell and it works! you can use that cell again by setting the details of your model object

cellForRowAtIndexPath:(0,6) provide object from array a index 6, which is b.png -- you attempt to dequeue an existing cell and it works! you can use that cell again by setting the details of your model object

cellForRowAtIndexPath:(0,7) provide object from array a index 7, which is b.png -- you attempt to dequeue an existing cell and it works! you can use that cell again by setting the details of your model object

cellForRowAtIndexPath:(0,8) provide object from array a index 8, which is b.png -- you attempt to dequeue an existing cell and it works! you can use that cell again by setting the details of your model object

cellForRowAtIndexPath:(0,9) provide object from array a index 9, which is b.png -- you attempt to dequeue an existing cell and it works! you can use that cell again by setting the details of your model object

Sorry for being so verbose! I hope this helps. Maybe it's worth working through a good table view tutorial. There will be many out there for sure.

Try with changing the identifier value for your cell .

NSString* identifierStr = [NSString stringWithFormat:@"ident_%d",indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifierStr];

You probably add images when you create the cell instances, instead of when the table view asks for a cell view. Example:

This is the right way. We set the image every time the table view asks for a cell.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ident"];
    UIImageView *imageView;
    if (cell == nil) {
        cell = [UITableViewCell alloc] init ....];
        imageView = [[UIIMageView alloc] init];
        imageView.tag = 123;
        [cell addSubview:imageView];
        [imageView release];
    } else {
        imageView = [cell viewWithTag:123];
    }

    imageView.image = ...; // load image here
}

This is the wrong way. We set the image when we create the cell. This will cause cells to have wrong images when they are re-used.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ident"];
    if (cell == nil) {
        cell = [UITableViewCell alloc] init ....];
        UIImageView *imageView = [[UIIMageView alloc] init];
        imageView.image = ...; 
        [cell addSubview:imageView];
        [imageView release];
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM