Antoine Lagadec
Antoine Lagadec

Reputation: 130

Adding subviews with a loop in UIScrollView generates memory leak

I'm new to Objective-C and I'm trying to make a Springboard like application. So I got an UIScrollView in which I make a loop to generate a bunch of subviews from another UIViewController.

Here's my code :

@implementation ProjectsListViewController {
    ProjectViewController *icon;
}

-

int row = 0;
int column = 0;
int page = 0;

for (int i = 0; i < 5; i++) {

    icon = [[ProjectViewController alloc] init];

    icon.iconPath = @"icon.png";
    icon.iconTag = i;

    int x = (1024 * page) + ((50 + (10 * column)) +  (188 * column));
    int y = (40 + (150 * row));

    icon.view.frame = CGRectMake(x, y, icon.view.frame.size.width, icon.view.frame.size.height);

    [self.scrollView addSubview:icon.view];

    // Add a new page if we reach the end of one
    if ((column == 4) && (row == 3)) {
        row = 0;
        column = 0;
        page++;

        // Add a new line if we reached last column
    } else if (column == 4) {
        column = 0;
        row++;

        // Add a column otherwise
    } else {
        column++;
    }
}

All of this stuff goes in the viewDidLoad method. Until there if I run the app everything's fine, icons are there. But when I want to click on an icon (there's a IBAction on a button to push to another view) my app crash because of possible memory leaks. It seems that there's no reference to the subviews anymore.

Only solution I found is to add each ProjectViewController inside a NSMutableArray. This way, I can click on icons and push another view.

Could someone explain me what I'm doing wrong ?

Sorry if it sounds noob to your ears, I'm trying to learn !

Note: I'm using ARC.

Upvotes: 1

Views: 971

Answers (4)

madmik3
madmik3

Reputation: 6983

if nothing is referencing the icon class outside of the loop it will be collected by ARC. that's why adding them to a list solves the problem. you are adding the icon's view to a list so they end up referenced. but nothing keeps track of the icons themselves.

Upvotes: 1

Jesse Black
Jesse Black

Reputation: 7986

Antoine the solution you made with the array works, I'd keep it like that.

To give insight to what is going wrong without the array
• icon is ProjectViewController (this is being created on the fly and being release by ARC)
• adding icon.view to any view will cause it to be retained by said view
• when the icon's action is triggered, it is attempting to message an instance of ProjectViewController that is no longer valid

Using your array (I am assuming it is a property (strong)), each instance of ProjectViewController added to the array will not be released by ARC and when your icon's action is triggered, the method is sent to a valid object.

Upvotes: 0

Hubert Kunnemeyer
Hubert Kunnemeyer

Reputation: 2261

instead of :

icon = [[ProjectViewController alloc] init];

I would do:

ProjectViewController *projectViewController = [[ProjectViewController alloc] init];

This way you create a new instance of ProjectViewController for every time through the loop, the other way reallocates the same UIViewController each time through.

Upvotes: 0

Andrew HunzekerHesed
Andrew HunzekerHesed

Reputation: 324

You should use UIButton's instead of images if they are being tied to to and IBAction. That way you are keeping your code modular and you don't have to worry about managing the memory of two different objects and actions.

Also, You should check out the last answer to this question: Why does static NSString leak?

Upvotes: 0

Related Questions