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 性能问题的主要内容,如果未能解决你的问题,请参考以下文章