2
votes

I'm using iCarousel to scroll labels. Everything works fine on Simulator, but on iPad/iPhone scrolling is not smoothly and quick

Here is code.

CitiesListView.h

#import <UIKit/UIKit.h>
#import "iCarousel.h"

@interface CitiesListView : UIView <iCarouselDataSource, iCarouselDelegate>

@property (nonatomic, retain)  iCarousel *carousel;


@end

CitiesListView.m

#import "CitiesListView.h"

@interface CitiesListView ()


@property (nonatomic, retain) NSMutableArray *items;

@end

@implementation CitiesListView

@synthesize carousel;
@synthesize items;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setUp];
    }
    return self;
}

- (void)setUp
{
    carousel = [[iCarousel alloc]initWithFrame:CGRectMake(0, 0, 300, 200)];
       items = [NSMutableArray arrayWithObjects:@"city1", @"city2", @"city3", @"city4", @"city5", @"city6", nil];
    [self addSubview:carousel];
    carousel.delegate = self;
    carousel.dataSource = self;
    carousel.type = iCarouselTypeRotary;

}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    if ((self = [super initWithCoder:aDecoder]))
    {
        [self setUp];
    }
    return self;
}

#pragma mark iCarousel methods

- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel
{
    return [items count];
}

- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
    UILabel *label = nil;

    //create new view if no view is available for recycling
    if (view == nil)
    {
        view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 200.0f)];
        ((UIImageView *)view).image = [UIImage imageNamed:@"labelBackground.png"];
        view.contentMode = UIViewContentModeCenter;
        label = [[UILabel alloc] initWithFrame:view.bounds];
        label.backgroundColor = [UIColor clearColor];
        label.textAlignment = UITextAlignmentCenter;
        label.font = [label.font fontWithSize:26];
        label.tag = 1;
        [view addSubview:label];
    } else {
        //get a reference to the label in the recycled view
        label = (UILabel *)[view viewWithTag:1];
    }

    //set item label
    //remember to always set any properties of your carousel item
    //views outside of the `if (view == nil) {...}` check otherwise
    //you'll get weird issues with carousel item content appearing
    //in the wrong place in the carousel
    label.text = [items objectAtIndex:index];
    return view;
}

- (NSUInteger)numberOfPlaceholdersInCarousel:(iCarousel *)carousel
{
    //note: placeholder views are only displayed on some carousels if wrapping is disabled
    return 2;
}

- (UIView *)carousel:(iCarousel *)carousel placeholderViewAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
    UILabel *label = nil;

    //create new view if no view is available for recycling
    if (view == nil)
    {
        //don't do anything specific to the index within
        //this `if (view == nil) {...}` statement because the view will be
        //recycled and used with other index values later
        view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200.0f, 200.0f)];
        ((UIImageView *)view).image = [UIImage imageNamed:@"labelBackground.png"];
        view.contentMode = UIViewContentModeCenter;

        label = [[UILabel alloc] initWithFrame:view.bounds];
        label.backgroundColor = [UIColor clearColor];
        label.textAlignment = UITextAlignmentCenter;
        label.font = [label.font fontWithSize:50.0f];
        label.tag = 1;
        [view addSubview:label];
    } else {
        //get a reference to the label in the recycled view
        label = (UILabel *)[view viewWithTag:1];
    }

    //set item label
    //remember to always set any properties of your carousel item
    //views outside of the `if (view == nil) {...}` check otherwise
    //you'll get weird issues with carousel item content appearing
    //in the wrong place in the carousel
    label.text = (index == 0)? @"[": @"]";

    return view;
}

- (CATransform3D)carousel:(iCarousel *)_carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform
{
    //implement 'flip3D' style carousel
    transform = CATransform3DRotate(transform, M_PI / 8.0f, 0.0f, 1.0f, 0.0f);
    return CATransform3DTranslate(transform, 0.0f, 0.0f, offset * carousel.itemWidth);
}

- (CGFloat)carousel:(iCarousel *)_carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value
{
    //customize carousel display
    switch (option)
    {
        case iCarouselOptionSpacing:
        {
            //add a bit of spacing between the item views
            return value * 1.05f;
        }
        case iCarouselOptionFadeMax:
        {
            if (carousel.type == iCarouselTypeCustom)
            {
                //set opacity based on distance from camera
                return 0.0f;
            }
            return value;
        }
        default:
        {
            return value;
        }
    }
}

#pragma mark iCarousel taps

- (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index
{
    NSNumber *item = [self.items objectAtIndex:index];
    NSLog(@"Tapped view number: %@", item);
}

@end

And in my view controller alloc/initWithFrame CitiesListView and added to self.view.

What I'm doing wrong. I need labels to scroll smooth like in examples.

Thanks.

4
You may want to profile your code in Instruments to see if there is a specific area that is affecting your app's performance. Use the Time Profiler instrument. See Apple's docs for more info on how to use Instruments: developer.apple.com/library/ios/#documentation/DeveloperTools/…stevekohls
when I profile and use allocations instrument carousel scrolls smooth. Cant find the issue and fixMariam
Allocations will tell you about your memory usage, but Time Profiler will let you know how much time each method is taking to execute. This may help find what is slowing down your drawing. Make sure you're profiling on the device too.stevekohls

4 Answers

0
votes

Inside your setUp method, call this:

carousel.centerItemWhenSelected = YES;

Also play with carousel.scrollSpeed (values: 0.0 to 1.0, default 1.0 which means fastest) to change the scrolling speed.

0
votes

Use any one method

  • (UIView *)carousel:(iCarousel *)carousel placeholderViewAtIndex:(NSUInteger)index reusingView:(UIView *)view

(Or)

  • (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
0
votes

The problem is fundamentally that you are trying to load too many images into memory at once (number of views x number of animation frames per view).

You'll need to find a way to load the frames dynamically. Try my GLView library (https://github.com/nicklockwood/GLView) which includes instructions for playing animations using PVR images which can be loaded in real time. The GLView library includes a GLImageView class that works just like a UIImageView but let's you specify an array of image filenames to play instead of having to load all the images in advance.

0
votes

This might help someone.I had similar issue where iCarousel was not scrolling smooth. Turns out i was doing some heavy validation(image comparison) in the method named - (void)carouselCurrentItemIndexDidChange:(iCarousel *)carousel

Once i kept only relevant validation which was light weight, issue was resolved.