找出缓慢加载的图像是我的collectionView不稳定的缓慢效果的背后。
我整天都在阅读不同的“问答”和各种论坛帖子。看来解决此问题的最佳方法是让cellForItemAtIndexPath可以预加载数据,以获取所需的数据。

我不确定该怎么做。我使用parse作为后端,但是请确保,如果给出一个粗略的示例,我将能够弄清楚该如何做。到目前为止,我需要一种单独的方法来获取数据。

这是代码:

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}


-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return [[self objects] count];
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
    NSArray *people = [self objects];
    static NSString *CellIdentifier = @"Cell";

    VAGGarmentCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier: CellIdentifier forIndexPath:indexPath];


    PFObject *current;

    current = [people objectAtIndex:indexPath.item];

    PFFile *userImageFile = current[@"image"];

    [userImageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
        UIImage *image = [UIImage imageWithData:imageData];

        [[cell contentView] setContentMode: UIViewContentModeScaleAspectFit];
        [[cell imageView] setImage:image];

    }];

    [[cell title] setText:[current valueForKey:@"title"]];
    [[cell price] setText:[NSString stringWithFormat: @"£%@", [current valueForKey:@"price"]]];

    return cell;

}

因此,也许cellForItemAtIndexPath需要调用该方法并获取所需的内容。因为数据已经可用,所以不需要将其加载到cellForItemAtIndexPath方法中,并且将立即填充单元格。

请提供建议和示例。

有人告诉我这样做的一个好方法是检查图像,如果不存在则提供一个占位符,如果确实存在则设置它。这是对以上代码的更改。

更新:
   -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{

    NSArray *people = [self objects];

    static NSString *CellIdentifier = @"Cell";

    VAGGarmentCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier: CellIdentifier forIndexPath:indexPath];



    PFObject *current;

    current = [people objectAtIndex:indexPath.item];



    PFFile *userImageFile = current[@"image"];

    [userImageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {

        if (!error)
        {

            if (!image) {
                [[cell imageView] setImage:[UIImage imageNamed:@"placeholder.png"]];


            }   else {

                image = [UIImage imageWithData:imageData];


                //resize image
                CGSize destinationSize = CGSizeMake(158,187);
                UIGraphicsBeginImageContext(destinationSize);
                [image drawInRect:CGRectMake(0,0,destinationSize.width, destinationSize.height)];

                //New image
                UIImage*newImage = UIGraphicsGetImageFromCurrentImageContext();
                UIGraphicsEndImageContext();

                //Optimise image
                NSData *imageDataCompressed = UIImageJPEGRepresentation(newImage, 0.4f);
                //  NSLog(@"Image Size %@", NSStringFromCGSize(newImage.size));//log size of image
                    NSLog(@"%@", [current valueForKey:@"title"]);


                [[cell imageView] setImage:[UIImage imageWithData:imageDataCompressed]];



            }

        }

    }];


    [[cell title] setText:[current valueForKey:@"title"]];
    [[cell price] setText:[NSString stringWithFormat: @"£%@", [current valueForKey:@"price"]]];


    return cell;

}

占位符可以正常显示,但仍然可以显示,如何知道何时加载图像,以便可以使单元格反映出来?

谢谢你的时间。
亲切的问候。

更新:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{

    NSArray *people = [self objects];

    static NSString *CellIdentifier = @"Cell";

    VAGGarmentCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier: CellIdentifier forIndexPath:indexPath];

    [cell.activityIndicator startAnimating];

    PFObject *current;

    current = [people objectAtIndex:indexPath.item];



    PFFile *userImageFile = current[@"image"];

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:userImageFile.url, indexPath.item]];
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url                                                                   cachePolicy:NSURLRequestReturnCacheDataDontLoad
                    timeoutInterval:6.0];
                    [cell.imageView setImageWithURLRequest:urlRequest
                    placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                    success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {

                    //resize image
                    CGSize destinationSize = CGSizeMake(158,187);
                    UIGraphicsBeginImageContext(destinationSize);
                    [image drawInRect:CGRectMake(0,0,destinationSize.width, destinationSize.height)];

                    //New image
                    UIImage*newImage = UIGraphicsGetImageFromCurrentImageContext();
                    UIGraphicsEndImageContext();

                    //Optimise image
                    NSData *imageDataCompressed = UIImageJPEGRepresentation(newImage, 0.4f);

                    cell.imageView.image = [UIImage imageWithData:imageDataCompressed];
                    NSLog(@"Image Size %@", NSStringFromCGSize(newImage.size));//log size of image
                   [cell.activityIndicator stopAnimating];

                    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError          *error) {
                    NSLog(@"Failed to download image: %@", error);
                                        }];




    return cell;

}

最新更新:

设置一种从parse.com获取数据并将其存储在NSMutableDictionary中然后存储在可变数组中的方法。我存储服装图像的标题,价格和URL。
- (void)grabDataFromCloud
{

    self.model = [NSMutableArray array];
    for (PFObject *object in [self objects]) {
        PFFile *imageFile = [object valueForKey:@"image"];
        NSURL *url = [NSURL URLWithString:imageFile.url];

        NSMutableDictionary *newObject = [NSMutableDictionary dictionaryWithDictionary:@{@"title": [object valueForKey:@"title"], @"price": [object valueForKey:@"price"], @"imageUrl": url}];
        [[self model] addObject:newObject];
    }
}

这在我的cellForItemsAtIndexPath方法中被调用。
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{

    [self grabDataFromCloud];
    static NSString *CellIdentifier = @"Cell";

    VAGGarmentCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier: CellIdentifier forIndexPath:indexPath];

    [cell.activityIndicator setHidden:YES];

    NSMutableDictionary* d = [self.model objectAtIndex:indexPath.item];
    cell.title.text = d[@"title"];
    cell.price.text = [NSString stringWithFormat:@"£%@", d[@"price"]];

    if (d[@"image"]) {
         cell.imageView.image = d[@"image"];
    } else { // if not, download it
        cell.imageView.image = nil;

        dispatch_queue_t backgroundQueue = dispatch_queue_create("test", 0);

        dispatch_async(backgroundQueue, ^{

             NSData* data = [NSData dataWithContentsOfURL:d[@"imageUrl"]];
             UIImage* img = [UIImage imageWithData:data];
             d[@"image"] = img;
                 dispatch_async(dispatch_get_main_queue(), ^{
                    //causes crash Assertion failure in -[UICollectionView _endItemAnimations],
                    // /SourceCache/UIKit/UIKit-2935.137/UICollectionView.m:3687
                     //   [self.collectionView reloadItemsAtIndexPaths:@[indexPath]];
                 });
        });

    }

        return cell;
    }

最佳答案

我建议您使用AFNetworking UIImageView+AFNetworking 类别。它将自动处理占位符等,并将在后台线程中执行所有操作,确保主线程不会被阻塞。具体来说,这是您要调用的方法:

- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage;

10-04 11:00
查看更多