iPad 上的 iCarousel 性能问题

Posted

技术标签:

【中文标题】iPad 上的 iCarousel 性能问题【英文标题】:iCarousel performance issue on iPad 【发布时间】:2013-04-05 10:05:23 【问题描述】:

我将 Nick Lockwood 的 iCarousel 用于 iPad 应用程序。现在它只是 15 张全屏图片的轮播。

我设置了一个单视图项目,在故事板中添加 iCarousel 视图,将其视图控制器添加为数据源,并将此代码用于数据源方法:

- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel 
    return 15;


- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view 
    UIImage* img = [UIImage imageNamed:[NSString stringWithFormat:@"image%d.jpg", index]];
    UIImageView* imgView = [[UIImageView alloc] initWithImage:img];

    return imgView;

这很有效,但是当我第一次滚动浏览所有项目时,您会注意到将新项目添加到轮播时性能会受到一点影响。我第二次检查所有项目时不会发生这种情况。

您可以在此分析器屏幕截图中看到我的意思。前半部分的峰值是我第一次滚动浏览所有图像,然后我再次滚动,没有峰值,也没有性能损失。

我该如何解决这个问题?

编辑

我隔离了仪器上的一个峰,这是调用树

编辑

带有 jcesar 建议的代码

- (void)viewDidLoad 
    [super viewDidLoad];

    NSMutableArray* urls_aux = [[NSMutableArray alloc] init];
    for (int i = 0; i<15; i++) 
        NSString *urlPath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"captura%d", i] ofType:@"jpg"];
        NSURL *url = [NSURL fileURLWithPath:urlPath];

        [urls_aux addObject:url];
    
    self.urls = urls_aux.copy;

    self.carousel.dataSource = self;
    self.carousel.type = iCarouselTypeLinear;


- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view 

    if (view == nil) 
        view = [[[AsyncImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)] autorelease];
        view.contentMode = UIViewContentModeScaleAspectFit;
    

    [[AsyncImageLoader sharedLoader] cancelLoadingImagesForTarget:view];
    ((AsyncImageView *)view).imageURL = [self.urls objectAtIndex:index];

    return view;

【问题讨论】:

可能是异步加载图片,他有一些这样加载图片的例子 你能解释一下你的答案吗? 是的,看看他的例子:github.com/nicklockwood/iCarousel/tree/master/Examples/…。他使用 AsyncImageView 代替 UIImageView,以异步方式加载图像。所以它不会尝试同时加载所有 15 张图片,我认为它不应该有性能问题 【参考方案1】:

我不认为这是一个非常正统的解决方案,但它确实有效。

我所做的是使用 iCarousel 的方法 insertItemAtIndex:animated: 在设置时一次添加一个图像。然后性能受到打击,但之后一切顺利。

- (void)viewDidLoad

    [super viewDidLoad];

    self.images = [[NSMutableArray alloc] init];
    self.carousel.dataSource = self;
    self.carousel.type = iCarouselTypeLinear;

    for (int i = 0; i<15; i++) 
        UIImage* img = [UIImage imageNamed:[NSString stringWithFormat:@"captura%d.jpg", i]];
        [self.images addObject:img];
        [self.carousel insertItemAtIndex:i animated:NO];
    


- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel 
    return self.images.count;


- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view 
    UIImage* img = [self.images objectAtIndex:index];
    UIImageView* imgView = [[UIImageView alloc] initWithImage:img];

    return imgView;

【讨论】:

【参考方案2】:

很难确定,但我猜第一次是从文件中加载图像;而第二次使用缓存副本 - 这是+[UIImage imageNamed:] 自动为您执行的操作;没有它,您每次都会看到性能受到影响。您可以更早地在您的应用委托或控制器的初始化程序中加载图像。

您可以做的另一件事是利用 iCarousel 的视图重用逻辑。我认为这与您的问题无关,但您现在不妨这样做:

- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view 
    UIImage* img = [UIImage imageNamed:[NSString stringWithFormat:@"image%d.jpg", index]];

    UIImageView* imgView = nil;
    if ([view isKindOfClass:[UIImageView class]])
    
        imgView = (UIImageView *)view;
        imgView.image = img;
        [imgView sizeToFit];
    
    else
    
        [[UIImageView alloc] initWithImage:img];
    

    return imgView;

更新:如果您能获得更多关于您的应用在哪里花费时间的信息,那就太好了。如果您使用Instruments Time Profiler,您可以了解每种方法所花费的时间百分比。

【讨论】:

重用仍然没有改变任何东西。我尝试将所有图像加载到 NSArray(甚至所有 UIImageViews)中,但它仍然是一样的。 重用现在不会改变任何事情,但这是明智之举。有趣的是阵列解决方案不起作用。您是否查看过 Instruments 以了解您的应用在哪里花费时间? 我为其中一个峰添加了调用树。【参考方案3】:

看看他的例子:Dynamic Downloads。他使用AsyncImageView 而不是UIImageView,以异步方式加载图像。所以它不会尝试同时加载所有 15 张图片,我认为它不应该有性能问题

【讨论】:

我尝试复制该代码。没有什么变化。我认为问题在于 icarousel 第一次设置图像,而不是在我从磁盘加载它们时。 看起来不错,然后没有线索。如果您使用全屏图像和线性模式,您是否考虑过 UICollectionViews?或 PSTCollectionView github.com/steipete/PSTCollectionView(ios >=4.3 的替代品)顺便说一句,muy buenas tus 应用程序,you fui uno de los que se quejo de que la de Jorge Drexler petaba en iOS 5 xD 我想我解决了它...(¡Gracias!En mi descargo diré que yo no programé la de Drexler, yo la idee he hice los prototipos de interacción)

以上是关于iPad 上的 iCarousel 性能问题的主要内容,如果未能解决你的问题,请参考以下文章

CATiledLayer PDF 在 iPad 3 Retina 显示屏上的性能很差

iCarousel 显示来自图像 URL 数组的图像

iOS 9:按钮上的黑色背景,以及某些设备上的性能错误

ipad 应用程序 - 方向旋转性能很差

iCarousel 滚动不顺畅

需要在icarousel中拖放视图