-1

I use xcode 4.4 with ARC on. I have dynamically created UIViews in the ViewController.m:

UIView* myviews[10];

Then in the - (void)viewDidLoad function i fill each of it with pictures i need

myviews[viewIndex] = [[UIView alloc]initWithFrame:myrec];
UIImage *testImg;
UIImageView * testImgView = [[UIImageView alloc]init];
testImg = [UIImage imageNamed:[NSString stringWithFormat:@"imgarray%d.png", viewIndex];
[testImgView setImage:testImg];
[myviews[viewIndex] addsubView:testImgView];
viewindex++;

So all seems to be fine, when i want to jump from one view to another i do with two buttons next:

[self.view addSubview:views[viewIndex]];
CATransition *animation = [CATransition animation];
[animation setDelegate:self];
[animation setDuration:1.0f];
[animation setType:@"rippleEffect"];
[animation setSubtype:kCATransitionFromTop];
//[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[self.view.layer addAnimation:animation forKey:@"transitionViewAnimation"];

Nothing seems to be bad, but the memory consumption grows with huge speed when i switch between views.. and then i get low memory warning or sometimes application will just crash.

I have tried to use UIViewController array and was switching between the controllers: nothing changes, the memory low warning is what i end up with..

Maybe i need to clean the memory somehow? But how? ARC does not allow to use release and so on..

last what i have tried (sorry, maybe not very professional) before to add new subview is this

NSArray *viewsToRemove = [self.view subviews];
                    for (UIView *views in viewsToRemove) {
                        [views removeFromSuperview];
                    }

But this does not help either.

EDIT: I need to clarify one thing: i need each UIView during the application execution, this means i can't release it before the application exit.

EDIT2: code is edited to look more alike the real code.

Andrei Golubev
  • 283
  • 1
  • 2
  • 15

4 Answers4

0

Why don't you use an NSMutableArray to store your views? it's much easier and I'd dare to say, much safer.

And also, when you remove them from the superview, also remove them from the array

As a general rule, remember that storing it into an array retains it, removing it releases it, so if you store it into an array, and then add it as a subview, it will have a retain count +2. You are then removing it from superview (retain count -1) but it will still be positive because it's still in your array.

Ismael
  • 3,927
  • 3
  • 15
  • 23
0

A few thoughts:

First, something's not right in the code as copied, as you never create testImgView. Instead of

testImgView.image = testImg;

you need

testImgView = [UIImageView viewWithImage:image];

Second, you don't need to go into layer animation. See this code instead...

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition: 110 forView:view cache:NO];  //110 for ripple effect
[UIView commitAnimations];

Third, you could try just adding all your views in viewDidLoad with tags and then setting visible.

mackworth
  • 5,873
  • 2
  • 29
  • 49
  • I answered below, yes the code is just an example on how do i create the UIViews with images. Your tip with the tags is a good idea but not in my case, i still need animation... It just seems that it does not pick my view from the array but creates it each time i try to add it. This is the only logical answer i see. But i must make it work. – Andrei Golubev Aug 28 '12 at 22:45
  • Oh and [UIView setAnimationTransition: 110 forView:view cache:NO] does not work in iOS 5.1 ?! I just have tried it and the view just changed as if there was no animation at all. – Andrei Golubev Aug 28 '12 at 22:51
  • Sorry, I forgot the addSubViews is not animatable. You'd need to manipulate the alpha instead. – mackworth Aug 28 '12 at 22:55
  • Well, yes, but unfortunately it's not what i need :( But i will try with the tags, seems to me a nice idea. But to me seems like the view will just add new views regardless if i remove previous from superview or not. The old one retains in memory and it causes the leak.. – Andrei Golubev Aug 28 '12 at 23:04
  • But if you only create them once, then it doesn't matter how many times they are retained. Are you using Instruments to tell you what's leaking? In particular, if you are creating them in ViewDidLoad, then every single time the parent view loads you're creating them again. Jason's dealloc code is important to ensure you're not leaking them. Alternatively, if you need them for the whole app lifetime, then move the array creation to applicationdidFinishLoading – mackworth Aug 29 '12 at 00:52
  • Hmm i noticed that when i use UIViewController array stored in NSMutableArray and modify it's view it consumes much less memory and in my case, with the 10 images, it worked. I did also placed the creation to applicationdidFinishLoading. Also i have noticed that first launch time of a UIView is much bigger than when i come back to it from another view, it means and i think this is what happens - when i dynamically create UIViews with content the iOS will cache it, and that's why it won't get released... And that's why it will retain the views I'n memory, consuming it. – Andrei Golubev Aug 29 '12 at 02:06
  • That is correct, see here... http://stackoverflow.com/questions/8644455/does-the-uiimage-cache-image So try -initWithContentsOfFile instead of +imageNamed – mackworth Aug 29 '12 at 02:09
0

If it's getting worse each time a transition occurs, you might try removing the animations from the layer when you remove from the superview.

NSArray *viewsToRemove = [self.view subviews];
                    for (UIView *views in viewsToRemove) {
                        [views removeFromSuperview];
                        [views.layer removeAllAnimations];
                    }
jordanperry
  • 3,368
  • 2
  • 19
  • 13
-1

When you use an array structure like this (I'm assuming as an ivar), ARC doesn't really know it has to release your views when your containing object's structure goes away. When you clean up, say in your -dealloc method, you need to just iterate through the array and set each element to nil, then ARC will know that it's okay to release that view. The other option is to use a Foundation collections type, such as an NSMutableArray to hold your views, which will free you from having to remember to clean them up.

For example:

- (void)dealloc
{
  for( int i = 0; i < 10; i++ )
    myviews[i] = nil;
}

If, during the lifetime of your application, you assign new views into this array, it's okay, ARC will do the right thing. Just make sure you nil them out in -dealloc. You can also release them earlier if you know you're done with them in the same way, i.e., iterating over the array and assigning nil to each element.

Jason Coco
  • 77,985
  • 20
  • 184
  • 180
  • Jason, i appreciate your answer, but i still need those views during the application execution... My problem is - when i switch between the views in the way i showed above, i get memory consumption increased each time i jump from one view to another.. – Andrei Golubev Aug 28 '12 at 22:01
  • @AndreiGolubev The memory consumption may then be caused by something else. How large are these 10 views? Is it possible this controller is being created multiple times and left around in memory? You need to check for those things, because if you just have these simple 10 static views, you shouldn't see any heap growth after each has been created and inserted into a view hierarchy at least once. – Jason Coco Aug 28 '12 at 22:06
  • No, the controllers/UIViews are created once and placed into an array, then i just switch between the array members by [self addsubView: myviews[viewIndex]];. The pictures are 20Mb in total, i doubt it may be the reason. May it? – Andrei Golubev Aug 28 '12 at 22:26
  • @AndreiGolubev 20MB decompressed? Also, I don't think that's your problem. If the code in your question is your actual code, you never even created an image view, and you never added your non-created image view to the view you created and stored in your array. When you assign the image, it's a no-op, since `testImgView` will be `nil` under ARC, `[testImgView setImage:testImg];` does nothing. – Jason Coco Aug 28 '12 at 22:29
  • @Jaison, no, it's not the actual code, it's just to give a hint on the problem because the actual code is massive but i can insure you, the meaning is the same. the part 2 and part 3 is the actual code snippets. And yes, the images are about 20mb and not compressed png. – Andrei Golubev Aug 28 '12 at 22:41