0

I have a UItableViewCell defined from a XIB file. This cell contains a UIScrollView, which is filled on the fly with UIView Objects - viewXY -. I use arc, everywhere in the code. The UI looks like:

cell 0: [ view00 view01 view02 ...]

cell 1: [ view10 view11 view12 ...]

etc..., where [ ] is a cell content, which is horizontally scrollable.

Problem: I profiled the app, and as I scroll down vertically, the memory footprint grows rapidly, and as far as I could see, never goes back to normal, nor reaches a plateau. More importantly, if I scroll down a few cells and then back up, memory increases too....

I checked for leaks with the instrument tool, nothing.

I narrowed down the problem around the part of the code that creates the viewXY . If I use:

myDisplay* viewXY;//myDisplay is a UIView subclass
-->viewXY = [[NSBundle mainBundle] loadNibNamed:AW_UI_VE owner:self options:nil][0];
[scrollView addSubview:viewXY];

Memory grows out of control as I flip through the cells. The NIB is a simple UIView+UIImageView+2 Labels.... If I replace say

UIImageView *viewXY = [UIImageView alloc] initWithImage:[blablabla]]
[scrollView addSubview:viewXY];

Everything is fine. The Live Bytes in instruments reaches rapidly a plateau.

As part of the tests, I load the NIB file without exercising any of the methods defined in its custom class, so it comes out with the IBOutlets as defined in the IB (default label text, image etc...).

This stuff is driving me crazy.

Suggestions to understand what I'm doing wrong are most welcome.

Alex
  • 1,581
  • 1
  • 11
  • 27
  • Just check scheme options in XCode (Product > Scheme > Edit Scheme > Run > Diagnostics tab) and ensure you have unchecked `Enable Zombie Objects` (NSZombieEnabled). – Ashok Jul 10 '15 at 00:44

3 Answers3

1

In your ViewController's viewDidLoad you should have something like this:

 [yourTable registerNib:[UINib nibWithNibName:@"yourUITableViewCellNibName" bundle:nil]
 forCellReuseIdentifier:@"reuseIdentifier"];

and in your table datasource method(cellForRowAtIndexPath) you should have the following:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     MyCustomCell* cell = [tableView dequeueReusableCellWithIdentifier:@"reuseIdentifier"];
     //Set your cell's values.

return cell;
}
Carlos
  • 1,319
  • 2
  • 17
  • 20
0

I’m not sure if this is related to the memory usage, but the docs recommend UINib for this use case:

Your application should use UINib objects whenever it needs to repeatedly instantiate the same nib data.

Another possibility is that there is a retain cycle in myDisplay. Does it have any strong properties that should be weak?

eager
  • 627
  • 6
  • 10
  • I thought about it, though with *myDisplay it shouldn't because it's created locally. So the reference disappear when the app leaves the function, and keeps only the one resulting from [scrollView addSubview:viewXY]. I do keep the list of viewXY in an array, so that I can call removeFromSuperview on them. When it is removed, then the pointer is assign nil manually. May be I should define this array to contain only weak reference ? – Alex Feb 24 '13 at 11:12
0
[scrollView addSubview:viewXY];

There is your problem. You're adding something to the scroll view, and never remove it.

From the sound of things, you aren't using the UITableView properly. You should have a view controller that impliments methods from UITableViewDelegate and UITableViewDataSource protocols, and use those to fill the table with data. You never add anything to the table directly, you only provide it with cells when it requests them.

RonLugge
  • 5,086
  • 5
  • 33
  • 61
  • for sake of clarity, I didn't include the whole code, but cells are created when cellsForRownAtIndexPath (UITableViewDataSource) is called. Also, viewXY is lazy-loaded, and then removed when it goes out of the view screen using removeFromSuperview. – Alex Feb 24 '13 at 10:46
  • @Alex be aware that you shouldn't just alloc cells, you should try to dequeue them and alloc them only if dequeue fails. (Actually, I believe in iOS 6 you can do both with the same function call) – RonLugge Feb 24 '13 at 21:34
  • now worries, as far as this part of the code is concerned, I do it "per the book". – Alex Feb 25 '13 at 10:02