找出缓慢加载的图像是我的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;