views:

1625

answers:

3

I have an app where I create many uiviews and add them to the self.view of the UIViewController. My app is running really slowly. I am releasing all of my objects and have no memory leaks (I ran the performance tool). Can anyone tell me what could be making my app so slow? (code is below)

[EDIT] The array has around 30 items. [/EndEdit]

Thanks so much!

Here is the code for the loadView method of my UIViewController:

- (void)loadView {

UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
contentView.backgroundColor = [UIColor whiteColor];
self.view = contentView;
[contentView release]; 



int length = 0;
for(NSString *item in arrayTips)
{
 length++;
 [item release];
}
int index = 0;
for(NSString *item in arrayTitles)
{
 SingleFlipView *backView = [[SingleFlipView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];



 backView.userInteractionEnabled = YES;
 backView.backgroundColor = [UIColor whiteColor];
 [backView setViewIndex:index];
 [backView setLastViewIndex:length];
 CGRect labelFrame = CGRectMake(10.0f, 0.0f, 300.0f, 30.0f);
 UILabel *backLabel = [[UILabel alloc] initWithFrame:labelFrame];
 backLabel.textAlignment = UITextAlignmentCenter;
 backLabel.userInteractionEnabled = YES;
 backLabel.text = item;
 backLabel.font = [UIFont fontWithName:@"Georgia" size:24.0f];
 backLabel.textColor = [UIColor blackColor];
 backLabel.backgroundColor = [UIColor whiteColor];

 CGRect textFrame = CGRectMake(10.0f, 30.0f, 300.0f, 110.0f);
 UITextView *tbxView = [[UITextView alloc] initWithFrame:textFrame];
 tbxView.textAlignment = UITextAlignmentCenter;
 tbxView.userInteractionEnabled = YES;
 tbxView.editable = FALSE;
 tbxView.text = [arrayTips objectAtIndex:index];
 tbxView.font = [UIFont fontWithName:@"Arial" size:14.0f];
 tbxView.textColor = [UIColor blackColor];
 tbxView.backgroundColor = [UIColor whiteColor];

 //CGRect labelFrame = CGRectMake(10.0f, 0.0f, 84.0f, 30.0f);
 UIImage *nextTip = [[UIImage imageNamed:@"NextTip.png"] retain];
 UIImageView *nextTipView = [ [ UIImageView alloc ] initWithImage:nextTip];
 nextTipView.frame = CGRectMake(230.0f, -10.0f, 84.0f, 30.0f);
 nextTipView.userInteractionEnabled = YES;


 UIImageView *view = [[ UIImageView alloc ] init];
 view.userInteractionEnabled = YES;
 if(self.sexString == @"Men")
 {
  UIImage *imgTip = [[UIImage imageNamed:@"feet_small.jpg"] retain];
  view.image = imgTip;
  view.frame = CGRectMake(0.0f, 110.0f, 416.0f, 228.0f); //59*161
  [imgTip release];
 }

 [backView addSubview:view];
 [backView addSubview:tbxView];
 [backView addSubview:backLabel];
 //[backView addSubview:nextTipView];

 [self.view addSubview:backView];
 [backView release];
 [backLabel release];
 [nextTip release];
 [nextTipView release];
 [tbxView release];
 [view release];

 index++;

 [item release];
}

}

+3  A: 

It's going to depend upon how many items are in arrayTitles. If you're just adding one or two of these, you shouldn't see a HUGE slowdown; more, and you will. You should probably take a look at the way UITableView handles its cells; only create these as they're actually needed/used, or, better yet, only create one of these, and set its contents on-the-fly.

A few other notes:

  • == is not a valid string comparison operator in Objective-C; use [string1 isEqualTo: string2]
  • It appears you're trying to place a lot of these on screen at the same time, which doesn't seem like it would make a lot of sense.
  • it looks like you've got a spurious [item release] at the end there (you're never retaining item, so there's no need to release it.
  • the whole first loop ( for(NSString *item in arrayTips)... frightens and confuses me; items in NSArrays are already retained by the array. You shouldn't have to explicitly retain/release them in this way.
Ben Gottlieb
Thank you for the notes, it's great to get some feedback on my code. This is my first real app so I'm still learning how best to architect my applications. It's trial and error at this point. I probably don't need all those views, but could simply change the label text based on the array.
rksprst
+2  A: 

Having deep view hierarchies can lead to slow downs that you can often fix through flattening them some with custom views, but if you are using simple views you can have dozens on the screen with no perceptible performance impact, so in general I recommend ignoring how many views you have when you are developing, and then reducing the view count if it proves to be a performance problem.

Having said that, you appear to be setting up something with an unboundedily large number of views which is not good. Without knowing how many entries there are in array titles I can't tell you what is going on exactly, but I suspect that while the actual visual heiarchy with each backView you are creating is fine, making a backView for each item in the array and using indices to have the front most one hide all the other ones behind it is causing you to have way too many views.

So, how to test it:

Add a break to the bottom of your for loop. Make the loop drop out after a single iteration and see if performance improves. If it does, then the huge view hierarchies are your issue. YOu may have to hack up the routine that changes the indexes to make sure it never swaps to an invalid index to test.

If that is the case you have a few options. You could implement a custom view and flatten every backview into a single view, but depending on how many you have that mat not be sufficient, and it is more work than simply building the back views the way you currently are, but on demand instead of at load time:

1) Refactor the code in your for loop into a separate method that makes a backView for a specific title and attaches it to the view at that time. 2) Where ever you are currently altering the indexes to make the backview visible, instead call the new method to actually build and attach the backview at that time

Louis Gerbarg
A: 

Don't forget to make as many of your views opaque as you can. Transparent views are a major source of performance issues.

Mark Bessey