views:

519

answers:

2

I have a data entry application that has the user enter about 6 pieces of information all on different views in a navigation controller. This works fine, but once the user gets used to the application the time it takes for the next screen to appear slows the user down.

I tried the application without the animations, but it doesn't feel quite right. Is there a way to get the animations to occur quicker? I'm primarily using a navigation controller, table views, and picker views.

A: 

Are you reusing cells in the table view? Make sure to really reuse them, in other words do all the setup of the cell inside the if(cell==nil) case and only apply the data in the common case (applying to both reuse and newly created).

Be aware of the performance hit that transparency can have in a cell. Often it seems that you have to make things transparent but maybe you don't because UITableViewCell is aware of the problems. Turning off transparency in some objects might seem wrong but is worth a try to see if it actually works. Most of the cost of scrolling a cell is the compositing as the cell moves, not creation of the cell initially.

Another thing that can help is doing the compositing of the view that you apply to your cell in advance rather than adding all the views to the cell, then you apply just one premade view to your cell.

If you are actually animating views in the scrolling cells you may need to rethink that or at least use some simplification to make it a little less taxing on the device.

You might also consider adopting Matt Gallagher's strategy for cell handling - it stops your cellForRowAtIndexPath turning into one long, nasty set of ifs.

Adam Eberbach
I don't think there's a performance problem in my code -- if I get rid of the animations the UI is a lot more snappy but a lot less iPhone-like.The problem is just that it takes some time for the animation to run. Instead of an animation that takes 0.5 seconds to run I'd like it to run in 0.25 seconds.Here's a fake example to make it clearer. Go to the calendar application and hit the right arrow to get the calendar to go to the next month. The next month will visually slide into view. My question is how would I get the next month to slide into view faster.
Epsilon Prime
I get it now - well I did see this:http://everburning.com/news/flicking-the-iphone/but there is a fair bit of manual work to do. I do not think you can change the speed of system transitions such as those caused by pushViewController:withAnimation in a way that will lead to app approval. I know of one way through accessing private methods that seemed to stop working with the release of 3.0.
Adam Eberbach
+1  A: 

There's going to be a penalty each time you load a new view, you could attempt to consolidate screens using a scroll view or a different layout. Also, if you are loading any unnecessary graphics you may want to remove them.

You could also add each view as a subview yourself in which case you have control over the animation duration among other things. This code will do that for you, although beware as I just wrote it and did not test it (The transition style and boolean parameters can be removed as they do nothing right now).

UIViewControllerExtendedPresentModalViewController.h

#import <Foundation/Foundation.h>

typedef enum _ExtendedModalTransitionStyle
{
    ExtendedModalTransitionStyleTopDown 
} ExtendedModalTransitionStyle;

@interface UIViewController ( ExtendedPresentModalViewController )
- (void)presentModalViewController: (UIViewController*)modalViewController 
         withTransitionStyle: (ExtendedModalTransitionStyle)style
           animated: (BOOL)animated;

- (void)dismissModalViewController: (UIViewController*)modalViewController
         withTransitionStyle: (ExtendedModalTransitionStyle)style
           animated: (BOOL)animated;
@end

UIViewControllerExtendedPresentModalViewController.m

#import "UIViewControllerExtendedPresentModalViewController.h"
#import <QuartzCore/QuartzCore.h>

@implementation UIViewController ( ExtendedPresentModalViewController )

    - (void)presentModalViewController: (UIViewController*)modalViewController 
             withTransitionStyle: (ExtendedModalTransitionStyle)style
               animated: (BOOL)animated
    {
        [modalViewController retain]; // we'll need this for a little while, hang on to it.

        CATransition* transition = [CATransition animation];
        [transition setDuration: 0.4];
        [transition setTimingFunction: 
         [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionLinear]];
        [transition setType: kCATransitionMoveIn];
        [transition setSubtype: kCATransitionFromBottom];
        [[[self view] layer] addAnimation: transition 
                 forKey: nil];
        [[self view] addSubview: [modalViewController view]];
    }

    - (void)dismissModalViewController: (UIViewController*)modalViewController
             withTransitionStyle: (ExtendedModalTransitionStyle)style
               animated: (BOOL)animated
    {
        CATransition* transition = [CATransition animation];
        [transition setDuration: 0.4];
        [transition setTimingFunction: 
         [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionLinear]];//kCAMediaTimingFunctionEaseInEaseOut]];
        [transition setType: kCATransitionReveal];
        [transition setSubtype: kCATransitionFromTop];
        [[[[modalViewController view] superview] layer] addAnimation: transition 
                       forKey: nil];
        [[modalViewController view] removeFromSuperview];

        [modalViewController release]; // all done, we can let this go.
    }
    @end
jessecurry
Thanks I'll try this.
Epsilon Prime
It will increase the amount of management you'll have to do, but could give you the extra speed that you need.
jessecurry
I haven't had time to try this specific code, but it's obvious I'm going to need to do all the transitions myself (as you suggest) instead of relying on the normal behavior.
Epsilon Prime