简体   繁体   中英

UICollectionView reorder cells after scrolling

I have added this UICollectionViewDelegate with my implementation:

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

    NSInteger index = indexPath.item + indexPath.section * 2;

    NSString *imagePath = [_images objectAtIndex:index];

    collectionViewCell.index = index;

    [collectionViewCell setImageWithPath:imagePath];

    collectionViewCell.delegateCell = self;

    return collectionViewCell;
}

In my custom cell I have this method:

- (void)setImageWithPath:(NSString *)imagePath
{
    if (!self.imageView)
    {
        CGRect rect = self.contentView.frame;

        self.imageView = [[UIImageView alloc] initWithFrame:rect];

        [self.contentView addSubview:self.imageView];

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            UIImage *image = [UIImage imageFromPath:imagePath];

            UIImage *resizedImage = [UIImage imageWithImage:image scaledToWidth:rect.size.width];

            dispatch_async(dispatch_get_main_queue(), ^{

                [self.imageView setImage:resizedImage];

            });
        });
    }
}

So as you can see if the cell does not have UIImageView then I start to create it and in background I get image from local path and resize it to cell content view width, then in main queue I set image to UIImageView.

This part work good but when I try to scroll my UICollectionView eg with 10 images I noticed that for example if first 2 top images were disappeared when I scroll down and then when I scroll back to the top, the images are changed placed.

This is state of images before scrolling down:

在此处输入图片说明

And this state after I scroll UIColectionView back to the top:

在此处输入图片说明

So as you can see first to item changed theirs location. As I have set if (!self.imageView) in my code above it should means that the image never will be created twice or more times.

I opened debugger and was checking this method:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

So the images paths returned one by one as it worked when UICollectionView just created cells at first time.

At first time first UICollectionViewCell has 0x8fbc1d0 and second has 0x8d0a4c0 address

But when I scroll down and then scroll up the debugger shown me second address at first 0x8d0a4c0 and then shown me 0x8fbc1d0

But I can't understand why items change theirs order. Or maybe here is another issue?

Also I don't have any method in the code that make for example for me reorder for cell. just few UICollection view methods delegate that configure count of cells and create them.

Also if I remove if (!self.imageView) seems everything works good, but then my code every time invoke dispatch that's no good for me, because when I resize image to the cell size I don't need do it twice.

When you scroll the two items off screen, your CollectionView puts the associated cells back onto the 'queue'. When you scroll back up again, the dequeueResuableCellwithReuseIdentifier in cellForItemAtIndexPath retrieves them from that queue, but (as you've seen) not necessarily in the same order. Thus the cell which was item 0 has been used for item 1 and vice versa. As you've seen, the if (!self.imageView) actually stops the correct image from being loaded. If you want to avoid retrieving and resizing them each time, then I would store the (resized) imageViews in an array.

- (void)setImageWithPath:(NSString *)imagePath
{
    if (!self.imageView)
    {
        CGRect rect = self.contentView.frame;

        self.imageView = [[UIImageView alloc] initWithFrame:rect];

        [self.contentView addSubview:self.imageView];

    }

    if (![self.imagePath isEqualsToString:imagePath] && self.imageView.image == nil)
        {
            self.imagePath = imagePath;

            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

                UIImage *image = [UIImage imageFromPath:imagePath];

                UIImage *resizedImage = [UIImage imageWithImage:image scaledToWidth:rect.size.width];

                dispatch_async(dispatch_get_main_queue(), ^{
                    if ([self.imagePath isEqualsToString:imagePath])
                    {
                        [self.imageView setImage:resizedImage];
                    }

                });

            });
        }
}

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