Reputation: 2552
I have a very strange problem when I'm testing my application on device. I have 2 views connected with Navigation Controller. My first view is very simple and has one UIButton. When clicking on this button happens switch to second view. My second view has UIButtons (>20) that are created programmatically. There is a problem, my switching animation work slower (than it should be) and with spurts. I tried to create same viewController with a lot of UIButtons but with Interface Builder and my animation is working correctly! This problem I have only when I'm testing application on real device, in simulator all of this variants work fine. Is there some difference in this two variants of creating UI elements? And how can I solve this problem with creating view with many of UI elements by programmatically (I prefer this way).
Edit1 I have a class whose superclass is UIButton. Here is implementation:
#import <QuartzCore/QuartzCore.h>
#import "UIHouseButtons.h"
@implementation UIHouseButtons
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self = [UIButton buttonWithType:UIButtonTypeRoundedRect];
UIImage *buttonImageNormal = [UIImage imageNamed:@"stateNormal.png"];
UIImage *strechableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[self setBackgroundImage:strechableButtonImageNormal forState:UIControlStateNormal];
UIImage *buttonImagePressed = [UIImage imageNamed:@"stateNormal.png"];
UIImage *strechableButtonImagePressed = [buttonImagePressed stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[self setBackgroundImage:strechableButtonImagePressed forState:UIControlStateHighlighted];
[[self layer] setCornerRadius:4.0f];
[[self layer] setMasksToBounds:YES];
[self.titleLabel setFont:[UIFont fontWithName:@"Times New Roman" size:15.0f]];
self.frame = frame;
}
return self;
}
After in my second view controller in -loadView
method:
UIHouseButtons *homeButton = [[UIHouseButtons alloc] initWithFrame:CGRectMake(435.0f, 5.0f, 40.0f, 25.0f)];
[homeButton setTitle:@"H" forState:UIControlStateNormal];
[self.view addSubview:homeButton];
and same 20 more times.
Edit 2 Edited my UIButtons class:
- (id)init
{
self = [super init];
if (self) {
self = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//self.backgroundColor = [UIColor clearColor];
UIImage *buttonImageNormal = [UIImage imageNamed:@"stateNormal.png"];
UIImage *strechableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[self setBackgroundImage:strechableButtonImageNormal forState:UIControlStateNormal];
UIImage *buttonImagePressed = [UIImage imageNamed:@"stateNormal.png"];
UIImage *strechableButtonImagePressed = [buttonImagePressed stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[self setBackgroundImage:strechableButtonImagePressed forState:UIControlStateHighlighted];
[[self layer] setCornerRadius:4.0f];
[[self layer] setMasksToBounds:YES];
[self.titleLabel setFont:[UIFont fontWithName:@"Times New Roman" size:15.0f]];
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = [[UIScreen mainScreen] scale];
}
return self;
}
My -viewDidLoad
:
- (void)viewDidLoad
{
[super viewDidLoad];
self.button1 = [[UIHouseButtons alloc] init];
self.button2 = [[UIHouseButtons alloc] init];
self.button3 = [[UIHouseButtons alloc] init];
self.button4 = [[UIHouseButtons alloc] init];
//and more 20 times
[self.view addSubview:self.button1];
[self.view addSubview:self.button2];
[self.view addSubview:self.button3];
[self.view addSubview:self.button4];
//and more 20 times
}
My viewWillAppear
:
-(void)viewWillAppear:(BOOL)animated {
[self.button1 setFrame:CGRectMake(13.0f, 5.0f, 30.0f, 30.0f)];
[self.button2 setFrame:CGRectMake(57.0f, 5.0f, 30.0f, 30.0f)];
[self.button3 setFrame:CGRectMake(99.0f, 5.0f, 30.0f, 30.0f)];
[self.button4 setFrame:CGRectMake(141.0f, 5.0f, 30.0f, 30.0f)];
//and more 20 times
[super viewWillAppear:animated];
}
Upvotes: 1
Views: 298
Reputation: 15213
You have no problems with the speed in the Simulator, because the Simulator is a simulator of an iPhone/iPad, but not an emulator of the hardware of the iPhone/iPad and it uses your computer's CPU&RAM.
There shouldn't be any difference in the performance of creating controls as long as you respect some rules when doing it programmatically and these are:
If you aren't using a nib file, override the method -loadView
and in there ONLY create a UIView
and set it to self.view
.
Then in -viewDidLoad
method initialize you view hierarchy - you subviews of self.view
, their subviews (buttons/labels/etc..). If you have hardcoded frame values you can set them here, but don't count on this, because in this method the view hierarchy geometry has not been setup correctly yet.
Then in -viewWillAppear:animated
method adjust all geometry and perform only lightweight operations, because this method should return as fast as it can (otherwise you may face glitches when presenting)..
UPDATE:
From your code snippet update I can see your buttons' layers have rounded corners. This can become a performance issue especially if the buttons are in UIScrollView. Set all your buttons' layer to rasterize in UIHouseButtons.m
file
self.layer.rasterizationScale = [[UIScreen mainScreen] scale]; //Add this if using images to adjust the proper rasterization scale for them.
self.layer.shouldRasterize = YES;
Upvotes: 3