iOS 5 cellForRowAtIndexPath Memory Leak - ios

I have been testing the application on the device (iOS 5) while using Instruments and I found a couple of memory leaks.
This is the part of the code I'm being redirected to from Instruments (see the arrow for exact line):
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CeldaUltimasFotosViewCell *cell =
(CeldaUltimasFotosViewCell *) [self.tableView
dequeueReusableCellWithIdentifier:#"CeldaUltimasFotosViewCell"];
if (cell == nil) {
- - - - > NSArray *topLevelObjects =
[[NSBundle mainBundle]
loadNibNamed:#"CeldaUltimasFotosViewCell"
owner:nil options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
// Configure the cell...
[[cell titulo] setFont:fuente_titulo];
...
return cell;
}
As you can see, I have a custom cell which is loaded from a NIB file. There are three files for the cell (customCell.m, customCell.h, customCell.xib). The thing is that I don't know if I have to release something in the cell controller (which is now empty, no methods), since this is iOS 5 with ARC.

check out my answer here:
How can I recycle UITableViewCell objects created from a XIB?
you don't even need to use loadNibNamed any more on iOS5

Take a look at the Table View Programming and how to load cells from NIB (XIB) files.
https://developer.apple.com/library/ios/#documentation/userexperience/conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//apple_ref/doc/uid/TP40007451-CH7-SW1
The first thing weird is that you are storing the cell in a local variable. You should be wiring the custom cell up to a property in the class and all you call in your code is:
[[NSBundle mainBundle] loadNibNamed:#"CeldaUltimasFotosViewCell" owner:self options:nil];
Follow the code from Loading Custom Table-View Cells From Nib Files and you can't go wrong.

Related

Custom UITableViewCell isn't released or reused after navigation, memory leak

I have a class that defines a custom contact cell called ContactItemCell and a xib file that lays out that cell. When I create the table view it opens up and six of these ContactItemCell classes are created. When I navigate back they aren't deallocated, and when I open the tableview again another 6 are created. Here's the tableview code:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Contact* contact = [self contactAtIndexPath:indexPath];
static NSString *cellID = #"ContactItemWithTagsForBothCell";
ContactItemCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil)
{
NSArray *arr = [[NSBundle mainBundle] loadNibNamed:#"ContactItemWithTagsForBothCell" owner:nil options:nil];
if (arr.count <= 0)
{
NSLog(#"couldnt find cell with ID: %#", cellID);
return nil;
}
cell = [arr firstObject];
}
[cell configureCellForContact:contact];
return cell;
}
The fileowner in the xib file is just set to be blank which I'm assuming means NSObject. I've tried looking for a strong reference cycle to see if the class is kept alive by pointers but I haven't seen anything after days of investigation. I'm really at my limit and I'm not sure what else I can do, I've been using instruments too and that's how I've figured out that they're being created 6 at a time but I can't find out what's pointing to them. Why is this happening? Am I doing something wrong with the table view? If I'm not and you think it's a strong reference cycle then how can I find every object that points to this ContactItemCell? Thanks in advance!
If anyone was curious I used the memory debugger and found that there was a strong reference cycle with a pod I was using.

hold data on tableview cell ios

I'm newbie in IOS and again i face another issue. How can i prevent data vanish from a table cell when i scroll a tableview.
I'm using the code below to load data on the table...Works fine but the data disappear when table cell go in not visible to the screen.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
list = [self.listas objectAtIndex:[indexPath row]];
static NSString *CellIdentifier = #"drop";
item_drop *cell = (item_drop*) [tabela_listas dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"item_drop" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.texto_drop.text = list.nome_lista;
return cell;
}
In android i used a holder to do it. There is anything similiar on IOS?
Since you are using reusable cells of a custom subclass of UITableViewCell, make sure you register the cell identifier in the UITableView, associating it to your custom cell type. i.e:
[yourTableView registerClass:[item_drop class] forCellReuseIdentifier:#"drop"];
You typically do this when you configure subviews in the UIViewController that controls the view your UITableView is a part of, in viewDidLoad.
With that in place, you should never hit the code inside if (cell == nil).

IOS image is not set in an image view

I am using the same code in two of my view controllers (they are implementing the same class what changes is the url they download) and in one occassion the image is displayed correclty while in the other I do see an empty cell.
Here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier=#"MyCell";
//this is the identifier of the custom cell
MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
tableView.backgroundColor=[UIColor clearColor];
tableView.opaque=NO;
tableView.backgroundView=nil;
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSLog(#"Image url is:%#",[images_url objectAtIndex:indexPath.row]);
NSURL *url_image=[NSURL URLWithString:[images_url objectAtIndex:indexPath.row]];
cell.myimage.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:url_image]];
return cell;
}
As i told you I have 2 view controllers implementing the same class. In the view did load the url is set depending on the value of a flag. If I open controller A, I see no image, if I open view B i can see the image. Both of the urls are correct as I can check it with the NSLog I have inserted.
What might be the problem?
Unfortunately calling "NSData dataWithContentsOfURL" is a blocking call. Execution of your program will stop until iOS is able to fetch all the data from the server or fails trying. This may often be "fast" if you're on LTE or WiFi; but can potentially take a LONG time.
Meanwhile, you're on the "main thread" in your app - so your app will appear to freeze-up, and the system's watchdog timer may kill your app. If anyone besides you will use this ap, you absolutely need to populate your tableview cell's image with local data that's retrieved immediately or use asynchronous methods.
Just google for "lazy load UIImage". This SO question has some good tips on the subject:
lazy-load-images-in-uitableview
Additionally, you should move these lines to some setup code. You don't need to perform them every time to update a cell:
tableView.backgroundColor=[UIColor clearColor];
tableView.opaque=NO;
tableView.backgroundView=nil;
Best of luck!

UITableView use xib to set cell,when Sliding it not smooth?

I have use xib set the interface,when using it dosen't smooth,why?
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomerCell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
NSArray * nib = [[NSBundle mainBundle] loadNibNamed:#"MSNeedCheckCell" owner:self options:nil] ;
cell = [nib objectAtIndex:0];
}
//填充cell的内容
}
Try calling the following method from your init method for the class:
[self.tableView registerNib:[UINib nibWithNibName:#"MSNeedCheckCell" bundle:nil]
forCellReuseIdentifier:#"CustomerCell"];
And then, you can remove your entire if (!cell) { section of code since it will always return a cell. This only loads the nib once instead of every time that you need a cell so will be much faster.
Is this, quite literally, all there is to it? Or are you doing anything else (e.g. in subclassed cell, or other code that you may have omitted for the sake of brevity).
The most common source of lack of smoothness (and by smoothness, I assume you're talking about a stuttering in the UI as you scroll in your tableview) would be if you're doing anything with images in the foreground queue.
The WWDC 2012 - 211 - Building Concurrent User Interfaces offers a wonderful, practical illustration of how to use Instruments to identify the sources of performance bottlenecks. Clearly they're focusing on a very specific design consideration there, but the Instruments tutorial is very useful. It would be good to make sure that this particular line of code is really the problem before you lose too much sleep over it.

More than one custom cell with in the same XIB

Is it possible to have more than one custom uitableviewCell within the same xib?
I'm trying to save XIB files by combining different customized cells within the same xib and then having the Table load different ones from it.
In IB, I tried setting each of the uiTableViewCell class to a different custom class .m/.h implementation. Here is what I tried:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"DevConfigCell";
DeviceInfoCell *cell = (DeviceInfoCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomTableViewCell~iphone" owner:self options:nil];
cell = ( DeviceInfoCell *)[nib objectAtIndex:0];
}
return cell;
}
In another table, i would reuse the nib, but i would do this:
cell = ( SecondDeviceInfoCell *)[nib objectAtIndex:0];
For some reason it always loads the first cell.
Should this all work? or is there a way?
Thanks
I'm trying to save XIB files by combining different customized cells
within the same xib
Why? There's no limit on the number of .xib files you can create.
and then having the Table load different ones from it.
When you load a .xib, all the objects that file contains are created. If you put 10 custom cells in one .xib, loading that .xib will create an instance of each of those 10 cells. That's probably not what you want. Keeping your cells in separate .xibs is probably a better plan.
cell = ( SecondDeviceInfoCell *)[nib objectAtIndex:0];
You seem to be confused about what casting does. When you cast from one type to another, you're not somehow selecting a different object. The object returned by [nib objectAtIndex:0] is always going to be the same if the nib array has the same contents. Casting just changes the type that the compiler associates with the value; in this case it changes the type of the pointer.
You can create an IBOutletCollection in your view controller and then connect several different custom cells to that outlet collection; that'll give you an array of cells that you can select from using objectAtIndex:. But again, that's really not a good idea since you'll be creating all the cells in the file every time you need just one.
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"PlayerAvgsTableCell" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[PlayerAvgsTableCell class]])
{
cell = (PlayerAvgsTableCell *)currentObject;
break;
}
}
}

Resources