Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UICollectionView使用AFNetworking加载图像的滚动性能_Ios_Objective C_Scroll_Afnetworking_Uicollectionview - Fatal编程技术网

Ios UICollectionView使用AFNetworking加载图像的滚动性能

Ios UICollectionView使用AFNetworking加载图像的滚动性能,ios,objective-c,scroll,afnetworking,uicollectionview,Ios,Objective C,Scroll,Afnetworking,Uicollectionview,我读过不少UICollectionView关于糟糕滚动的帖子,但似乎没有一篇直接适用,或者它们仍然没有得到回答 我使用AFNetworking将图像(95px平方)异步加载到每个单元格中,然后当图像再次滚动到视图中时,图像从缓存中恢复(由响应代码0而不是200验证) 以下是我尝试过的: 注释掉weakCell.photoView.image=image这样图像就不会在屏幕上绘制,滚动也更平滑(在HTTP get过程中仍然有点结巴) 从cellforrowatinedxpath方法中删除了所有A

我读过不少UICollectionView关于糟糕滚动的帖子,但似乎没有一篇直接适用,或者它们仍然没有得到回答

我使用
AFNetworking
将图像(95px平方)异步加载到每个单元格中,然后当图像再次滚动到视图中时,图像从缓存中恢复(由响应代码0而不是200验证)

以下是我尝试过的:

  • 注释掉
    weakCell.photoView.image=image这样图像就不会在屏幕上绘制,滚动也更平滑(在HTTP get过程中仍然有点结巴)
  • cellforrowatinedxpath
    方法中删除了所有AFNetworking代码,滚动更加平滑(即使自定义单元格阴影等仍在屏幕上绘制)
  • 当我在屏幕上只绘制单元视图(带阴影)时,100个单元的滚动非常平滑。当我开始在屏幕上绘制图像时,我的设备上的滚动效果很差,甚至在模拟器上也很明显。Instagram在他们的个人资料视图上有数百个单元格,滚动非常平滑,所以我试图接近他们的性能
有什么方法可以改进下面的代码以提高滚动性能吗?

这是我的手机号码:

#import "PhotoGalleryCell.h"

@implementation PhotoGalleryCell

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        // Setup the background color, shadow, and border
        self.backgroundColor = [UIColor colorWithWhite:0.25f alpha:1.0f];
        self.layer.borderColor = [UIColor blackColor].CGColor;
        self.layer.borderWidth = 0.5f;
        self.layer.shadowColor = [UIColor blackColor].CGColor;
        self.layer.shadowRadius = 3.0f;
        self.layer.shadowOffset = CGSizeMake(0.0f, 2.0f);
        self.layer.shadowOpacity = 0.5f;

        // Make sure we rasterize for retina
        self.layer.rasterizationScale = [UIScreen mainScreen].scale;
        self.layer.shouldRasterize = YES;

        // Add to the content view
        self.photoView = [[UIImageView alloc] initWithFrame:self.bounds];
        [self.contentView addSubview:self.photoView];
    }

    return self;
}

- (void)prepareForReuse
{
    [super prepareForReuse];

    self.photoView.image = nil;
    self.largeImageURL = nil;
}
这是我的UICollectionView代码:

#pragma mark - Collection View Delegates

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

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

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    PhotoGalleryCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kPGPhotoCellIdentifier forIndexPath:indexPath];

    // Get a reference to the image dictionary
    NSDictionary *photoDict = [[zePhotos objectAtIndex:indexPath.row] objectForKey:@"image"];

    // Asynchronously set the thumbnail view
    __weak PhotoGalleryCell *weakCell = cell;
    NSString *thumbnailURL = [[photoDict objectForKey:@"thumbnail"] objectForKey:@"url"];
    NSURLRequest *photoRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:thumbnailURL]];
    [cell.photoView setImageWithURLRequest:photoRequest
                          placeholderImage:nil
                                   success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
                                       weakCell.photoView.image = image;
                                   }
                                   failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
                                       NSLog(@"Error retrieving thumbnail... %@", [error localizedDescription]);
                                   }];

    // Cache the large image URL in case they tap on this cell later
    cell.largeImageURL = [[photoDict objectForKey:@"large"] objectForKey:@"url"];

    return cell;
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    [self performSegueWithIdentifier:@"showPhotoDetail" sender:self];
}

代码检查看起来不错,尽管我打赌是阴影的合成增加了很多延迟。要准确找出造成延迟的原因,可以在仪器中使用时间分析器工具

问题是,当您快速滚动时,您同时启动了数百个网络请求。如果缓存了图像,请立即显示它。如果没有,请仅在表视图速度减慢时开始下载

您可以使用以下内容:

//Properties or Instance Variables
NSDate *scrollDateBuffer;
CGPoint scrollOffsetBuffer;

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{   
    NSTimeInterval secondsSinceLastScroll = [[NSDate date] timeIntervalSinceDate:scrollDateBuffer];
    CGFloat distanceSinceLastScroll = fabsf(scrollView.contentOffset.y - scrollOffsetBuffer.y);

    BOOL slow = (secondsSinceLastScroll > 0 && secondsSinceLastScroll < 0.02);
    BOOL small = (distanceSinceLastScroll > 0 && distanceSinceLastScroll < 1);

    if (slow && small) {
        [self loadImagesForOnscreenRows];
    }

    scrollDateBuffer = [NSDate date];
    scrollOffsetBuffer = scrollView.contentOffset;
}
我把它放在try/catch块中,因为根据我的经验,
[UITableView-visibleCells]
不可靠-它偶尔会返回释放的单元格或没有superview的单元格。如果您确保仅在表没有快速滚动时调用此方法,则不会对滚动性能产生太大影响


另外,请注意,AFUIImageView类别不公开缓存对象。您需要稍微修改它,以检查是否已经缓存了图像;应该会为您指明正确的方向。

您可以尝试向cell init添加阴影路径,这会提高性能,这就是我在一个项目中添加圆形阴影路径的代码(有关更多选择,请参阅UIBezierPath方法)

此外,如果我没记错,AFNetworking不会调整从服务器返回的图像的大小,因此可能会影响图像的质量(尽管您在UIImageView中添加了缩放方法),如果您愿意,我建议调度返回的图像以调整其大小:

CGSize targetSize = cell.photoView.bounds.size;
[cell.photoView setImageWithURLRequest:photoRequest
                      placeholderImage:nil
                               success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
                                    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                                       CGFloat imageHeight = image.size.height;
                                       CGFloat imageWidth = image.size.width;

                                       CGSize newSize = weakCell.imageView.bounds.size;
                                       CGFloat scaleFactor = targetSize.width / imageWidth;
                                       newSize.height = imageHeight * scaleFactor;

                                       UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
                                       [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
                                       UIImage *small = UIGraphicsGetImageFromCurrentImageContext();
                                       UIGraphicsEndImageContext();

                                       dispatch_async(dispatch_get_main_queue(),^{
                                           weakCell.photoView.image = small;
                                       });
                                   });
                               }
                               failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
                                   NSLog(@"Error retrieving thumbnail... %@", [error localizedDescription]);
                               }];

当我在屏幕上只绘制单元视图(带阴影)时,100个单元的滚动非常平滑。当我开始在屏幕上绘制图像时,我的设备上的滚动效果很差,甚至在模拟器上也很明显。Instagram在他们的个人资料视图中可以平滑地滚动数百个单元格,因此我试图接近他们的性能。请注意,我的答案包括有关UITableView的信息,而您使用的是UICollectionView。同样的答案也适用,因为UICollectionView遵循相同的设计模式。很抱歉响应太晚!AFNetworking应该已经针对UIScrollView的任何子类(如您列出的子类)进行了优化,因此应该已经注意到这一点。您是否成功地解决了此问题?“我正在做同样的事情,如果你有后续行动,我将非常感激。”@Tres抱歉,但我现在不得不接受这次表演。AFNetworking表示它已经针对UIScrollView的任何子类(如UITableView或UICollectionView)进行了优化,但这似乎是UI性能差的原因。谢谢您的回答。正如我在OP中所说:当我只在屏幕上绘制单元格视图(带阴影)时,100个单元格的滚动非常平滑。当我开始在屏幕上绘制图像时,我的设备上的滚动效果很差,甚至在模拟器上也很明显。因此,这似乎是网络图像缓存的一个问题。
self.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.frame.bounds
                                              byRoundingCorners:UIRectCornerAllCorners
                                                    cornerRadii:CGSizeMake(10, 10)].CGPath;
CGSize targetSize = cell.photoView.bounds.size;
[cell.photoView setImageWithURLRequest:photoRequest
                      placeholderImage:nil
                               success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
                                    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                                       CGFloat imageHeight = image.size.height;
                                       CGFloat imageWidth = image.size.width;

                                       CGSize newSize = weakCell.imageView.bounds.size;
                                       CGFloat scaleFactor = targetSize.width / imageWidth;
                                       newSize.height = imageHeight * scaleFactor;

                                       UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
                                       [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
                                       UIImage *small = UIGraphicsGetImageFromCurrentImageContext();
                                       UIGraphicsEndImageContext();

                                       dispatch_async(dispatch_get_main_queue(),^{
                                           weakCell.photoView.image = small;
                                       });
                                   });
                               }
                               failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
                                   NSLog(@"Error retrieving thumbnail... %@", [error localizedDescription]);
                               }];