Search code examples
iosobjective-cicarousel

iCarousel performance issue on iPad


I'm using Nick Lockwood's iCarousel for an iPad app. Right now it's just a carousel of 15 full screen images.

I setup a single view project, add the iCarousel view in storyboard, add it's view controller as a data source and put this code for the datasource methods:

- (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;
}

This works, but the first time I scroll through all the items you can notice a little performance hit when a new item is being added to the carousel. This does not happen the second time I go through all the items.

You can see what I mean in this profiler screenshot. The peaks in the first half are for the first time I scroll through all the images, then I do it again and there are no peaks and no performance hit.

How can I fix this?

enter image description here

EDIT

I isolated one of the peaks on instruments and this is the call tree

enter image description here

EDIT

The code with jcesar suggestion

- (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;
}

Solution

  • I don't think this is a very orthodox solution, but it works.

    What I do is use iCarousel's method insertItemAtIndex:animated: to add the images one at a time on setup. Performance gets hit then, but after that everything runs smoothly.

    - (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;
    }