Custom cell code showing leaks in iPhone - iphone

this may be a simple question but i can't figure the solution.Im creating a custom cell for a table view.When I'm testing the app instruments is showing leaks in code used for creating custom cell.I don't understand where i have to release the stuff for removing the leaks.Can anyone give me a hand for this.
This is the code i used for creating the custom cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID= #"Parcustom";
Parcustom *cell = (Parcustom *)[tableView dequeueReusableCellWithIdentifier:cellID];
if(cell==nil)
{
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"Parcustom" owner:nil options:nil];
for(id currentObject in nibObjects)
{
if([currentObject isKindOfClass: [Parcustom class]])
{
cell = (Parcustom *)currentObject;
}
}
} // Configure the cell...
cell.f1.text=[datedisplay objectAtIndex:indexPath.row];
cell.f2.text=[tips objectAtIndex:[[indexx objectAtIndex:indexPath.row]intValue]];
cell.selectionStyle=UITableViewCellSelectionStyleGray;
return cell;
}
The instrument is saying leak in the line NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"Parcustom" owner:nil options:nil];
How can i remove this leak.Can anyone help me please.

Replace below code with if block
NSArray *nibObjects = [[NSArray alloc] initWithArray:[[NSBundle mainBundle] loadNibNamed:#"Parcustom" owner:nil options:nil]];
for(id currentObject in nibObjects)
{
if([currentObject isKindOfClass: [Parcustom class]])
{
cell = (Parcustom *)currentObject;
}
}
[nibObjects release];

It seems there is no leak in the code presented. I suppose actual leak is somewhere in Parcustom class. Perhaps you don't release some ivar in Parcustom's dealloc. Maybe f1 or f2.

I don't see a leak in your code - Try running the static analyzer ("Analyze" in XCode's menu) and see if it reports a leak. If it does, you can expand the information about the leak and see the root cause.

Related

Returning 'self' while it is not set to the result of '[(super or self) init...]' in my custom alloc method

I init my custom view with my custom method :
1) In My View Controller I am calling custom view and pass this array to my custom class that is of type UIView
NSArray *array = [[NSBundle mainBundle] loadNibNamed:#"CustomViewiPhoneLayout" owner:self options:nil];
customViewObject = [[CustomView alloc] initWithArray:array];
[ParentLayout addSubview:customViewObject];
2) Custom View.
-(id)initWithArray:(NSArray*)array {
self = [array objectAtIndex:0]; // passing view as self; here it shows leak.
if(self) {}
return self;
}
It giving me possible leak named Returning 'self' while it is not set to the result of '[(super or self) init...]'
For sure you don't need this, as far as:
NSArray *array = [[NSBundle mainBundle] loadNibNamed:#"CustomViewiPhoneLayout" owner:self options:nil];
customViewObject = [array objectAtIndex:0];
In your code you alloc a view and loose it assigning self.
I have the same problem, i fix it by remove these code
NSArray *array = [[NSBundle mainBundle] loadNibNamed:#"CustomViewiPhoneLayout" owner:self options:nil];
customViewObject = [array objectAtIndex:0];
from the definition init method.
use above code at the place where you create the custom view rather than in custom's definition body.
The compiler is complaining because you are using an init function without using one of the super functions. Although it may make logical sense, it is technically misuse of the init function, and this is why the compiler is complaining. This will not always be a problem (I had some code that only gave me a warning on it before I fixed it), but it is a good practice not to work that way. In this case, this is not proper use of the init function. I would write another function like this:
+(customViewObject *)createWithArray:(NSArray *)array{
customViewObject *returnObject = [array objectAtIndex:0];
return returnObject;
}
However, looking at the first bit of code, I see no need to have a function of this sort in the customViewObject class. I would recommend simply doing this:
NSArray *array = [[NSBundle mainBundle] loadNibNamed:#"CustomViewiPhoneLayout" owner:self options:nil];
customViewObject = [array objectAtIndex:0];
[ParentLayout addSubview:customViewObject];

Customizing UITableViewCell in Interface Builder

In two classes, I've subclassed UITableViewCell in order to do some major customization. I'd like to use a Xib file to keep the amount of UI layout code to a minimum. I'm coming across an odd exception:
if (!cell) {
if (indexPath.row == 0) {
cell = [[[SearchCellTop alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
NSArray* objects = [[NSBundle mainBundle] loadNibNamed:#"SearchCellTop" owner:cell options:nil];
cell = (SearchCellTop*)[objects objectAtIndex:0];
}
else {
cell = [[[SearchCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
NSArray* objects = [[NSBundle mainBundle] loadNibNamed:#"SearchCell" owner:cell options:nil];
cell = (SearchCell*)[objects objectAtIndex:0];
}
}
This seems to work well for loading the Xibs. However as soon as I try doing something such as:
if (indexPath.row < [self tableView:tableView numberOfRowsInSection:indexPath.section])
((SearchCell*)cell).Product = [products objectAtIndex:indexPath.row];
I get -[UIAccessibiltyBundle setProduct:] unrecognized selector sent to instance
Everything indicates that 'cell' is of the correct type, however I'm stilling getting this error.
From Apple's developer documentation for the + (BOOL)loadNibNamed:(NSString *)aNibName owner:(id)owner method:
owner
The object to assign as the nib FIle's Owner. If the class of this object has an associated bundle, that bundle is searched for the specified nib file; otherwise, this method looks in the main bundle.
In your case, the owner should be nil (or a specific bundle, if associated).
In the code, change the calls to the loadNibNamed method as following:
NSArray* objects = [[NSBundle mainBundle] loadNibNamed:#"SearchCellTop" owner:nil options:nil];
NSArray* objects = [[NSBundle mainBundle] loadNibNamed:#"SearchCell" owner:nil options:nil];

What is causing a BUS_ADRALN in [[NSBundle mainBundle] loadNibNamed?

Our application is occasionally getting a BUS_ADRALN. Looking at the crash log it shows the line [[NSBundle mainBundle] loadNibNamed:#"MyCell" owner:self options:nil]. I know a BUS_ADRALN is an invalid address, but I'm not seeing the problem. It works most of the time.
static NSString *buddyListCellId = #"MyCell";
cell = [tableView dequeueReusableCellWithIdentifier:buddyListCellId];
if (cell == nil) {
// the following line is what the crash is pointing to
[[NSBundle mainBundle] loadNibNamed:#"MyCell" owner:self options:nil];
cell = buddyListCell;
self.buddyListCell = nil;
}
That's pretty straightforward. What's the code leading up to it? Perhaps MyCell.nib is corrupt, try a clean and rebuild perhaps (your distribution on the device could be corrupt perhaps)

iphone: to much memory consumption and leak in case of table view

I am preparing custom cells like this
1) Created a custom cell with Xib
2) since I have to change content of lables in custom cell corresponding to values read from database. I cant reuse same cellIdentifier
static NSString *MyIdentifier = #"MyIdentifier";
MyIdentifier = [NSString stringWithFormat:#"Cell %d",indexPath.row];
NSString *offendersImagePath = [self applicationDocumentsDirectory];
offendersImagePath=[offendersImagePath stringByAppendingPathComponent:#"Images"];
CustomOffendersCell *cell = (CustomOffendersCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if(cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"CustomOffendersCell" owner:self options:nil];
cell = aCustomOffendersCell;
aCustomOffendersCell=nil;
}
NSMutableArray *tempArray;//=[[NSMutableDictionary alloc] init];
tempArray=[offendersNamesList objectAtIndex:indexPath.row];
the code goes like above when I checked this thing in instruments its showing leak for this line and high memory consumption
[[NSBundle mainBundle] loadNibNamed:#"CustomOffendersCell" owner:self options:nil];
can you suggest me some way to get rid of this
You should call "release" method for cell like "[aCustomOffendersCell release]".
Also you have to release all the data which you have alloc in cell like UILabel, UIImageView, etc... So, when you put it inside the cell, then release these all data.
Hope it will helpful to you. And let me know for more details.
you should call autorelease on aCustomOffendersCell instead of just assigning nil.
aCustomOffendersCell nil;
Use below
[aCustomOffendersCell autorelease];

UIImageView not showing up in custom UITableViewCell

Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ConvoreCell";
ConvoreCell * cell = (ConvoreCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ConvoreCell" owner:nil options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (ConvoreCell *) currentObject;
break;
}
}
}
NSMutableDictionary *cellValue = [results objectAtIndex:indexPath.row];
NSString *picURL = [[cellValue objectForKey:#"creator"] objectForKey:#"img"];
if ([picURL isEqualToString:#"https://secure.gravatar.com/avatar/1f043010eb1652b3fab3678167dc0487/?default=https%3A%2F%2Fconvore.com%2Fmedia%2Fimages%2Feric.png&s=80"])
picURL = #"https://convore.com/media/images/eric.png";
if ((picURL != (NSString *) [NSNull null]) && (picURL.length !=0)) {
NSLog(#"%#", picURL);
NSData *imgData = [[[NSData dataWithContentsOfURL:
[NSURL URLWithString:
picURL]] autorelease] retain];
[cell.pic initWithImage:[[UIImage alloc] initWithData:imgData]];
} else {
cell.pic = nil;
}
//NSLog(#"Name is : %#", [cellValue objectForKey:#"name"]);
cell.title.text = [cellValue objectForKey:#"name"];
cell.info.text = (#"Created by: %#", [[cellValue objectForKey:#"creator"] objectForKey:#"name"]);
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// Configure the cell...
return cell;
}
For some reason the image is not showing up. What am I doing wrong here? The URL of the image is valid, I checked.
Also I don't want to have the accessory view on the TableViewCell, I did specify that as no in IB, but it still shows up... i set the accessory attribute to none already
you have some issues in your code.
NSData *imgData = [[[NSData dataWithContentsOfURL:
[NSURL URLWithString:
picURL]] autorelease] retain];
the former is not a real issue (maybe by coincidence?!), but it's ugly and confusing. get rid of the autorelease and the retain. The object you get from dataWithContentsOfURL: is already autoreleased.
[cell.pic initWithImage:[[UIImage alloc] initWithData:imgData]];
And your real issue might be this. From what I know you should call init exactly one time; after you've allocated an object.
So if cell.pic is an UIImageView I would try to change the code to something like this:
cell.pic.image = [[[UIImage alloc] initWithData:imgData] autorelease];
Once you see your images you should change your code so that it saves the images in the data you use to populate the cell. You are downloading the image every time a cell appears. That's something you shouldn't do. But this is beyond this question.
EDIT:
Also I don't want to have the
accessory view on the TableViewCell, I
did specify that as no in IB, but it
still shows up... i set the accessory
attribute to none already
You do? But I can see this line of code:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
You should be able to get an UIImage by just
[cell.pic initWithImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSUrl NSURL picURL]]]];
You're not showing your cellForRowAtIndexPath method, which is the key to analyzing what's going on. The typical paradigm is that UITableViewCell objects get reused repeatedly by the UITableView. You should be setting the UIImage into the cell when the UITableView calls cellForRowAtIndexPath.
The problem causing your immediate crash is that the nib for ConvoreCell is trying to set an IBOutlet you have declared but finding no way to actually set it. I would check that you have synthesized your pic property.
There are other problems here. The line
[cell.pic initWithImage:[[UIImage alloc] initWithData:imgData]];
Is wrong; you do not call init on an object that already exists, but only when you are allocating an object. Do something like
cell.pic = [[[WhateverClassPicIS alloc] initWithImage:[[UIImage alloc] initWithData:imgData]];
Also, you are using NSData dataWithContentsOfURL on the main thread. This will lock up your user interface for an indeterminate time as you connect to the network. Use asynchronous calls instead.