EXEC_BAD_ACCESS in UITableView cellForRowAtIndexPath - ios

My UITableView is returning EXEC_BAD_ACCESS, but why!
See this code snippet!
Loading the UITableView works fine, so allXYZArray != nil and is populated!
Then scrolling the tableview to the bottom and back up causes it to crash, as it goes to reload the method cellForRowAtIndexPath
It fails on line:
"NSLog(#"allXYZArray::count: %i", [allXYZArray count]);"
(UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAt
IndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [theTableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
#try
{
if (allXYZArray == nil) {
NSLog(#"nil");
allXYZArray = [ToolBox getMergedSortedDictionaries:allXYZGiven SecondDictionary:allXYZSought];
}
NSLog(#"%i", [indexPath row]);
NSLog(#"allXYZArray::count: %i", [allXYZArray count]);

EXC_BAD_ACCESS means that your program is trying to access a memory address that is invalid or otherwise inaccessible from your process. This most commonly happens when you try send a message to an object that has already been dealloced. So the first step in debugging EXC_BAD_ACCESS is to figure out which object your program was trying to send a message to when the crash happened. Often the answer isn't obvious, in which case, NSZombieEnabled is a great tool for identifying which line of code caused the crash.
In your case you've already determined that the crash happens when you call [allXYZArray count], making allXYZArray our prime suspect. This object is being returned from +[ToolBox getMergedSortedDictionaries:SecondDictionary:], so it's likely that your bug is in the implementation of that method. I would guess that it's returning an object that has already been released instead of autoreleased, as prescribed by the Memory Management Programming Guide for Cocoa. (This is one of the most important documents in the SDK, by the way. I recommend rereading it once a month until its policies and techniques become second nature.)

Ok, reusing a cell, does not guarantee that the cell will be initialized properly:
UITableViewCell *cell = [theTableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell will sometimes be null (especially the first time I guess).
Check cell for null and if so, initialize it properly.
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

Related

EXC_BAD_ACCESS only when returning from scrolling all the way down in a UITableView

EXC_BAD_ACCESS(code=1, address=0x71474b80)
This error appears when the user returns from scrolling all the way down in a nested UITableView. If I don't scroll to the bottom, the error doesn't happen.
maybe there is a deallocation problem as suggested by
UIViewTableController: "EXC_BAD_ACCESS" When Scrolling Up/Down Past the Max Position of the Table
My code is:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"TroncalesInfo";
TroncalesViewCell *cell = [[TroncalesViewCell alloc]init];
cell = [tabla dequeueReusableCellWithIdentifier:CellIdentifier];
cell.IDTroncal = [nombresTroncales objectAtIndex:indexPath.row];
[cell setCellAtributes:indexPath db:dataBase];
return cell;
}
This is a little hack I always use. I don't know exactly why it works, but give it a try ;).
Insert this in the viewWillDisappear of your viewController:
tabla.delegate = nil;
I don't know if this is the source of your problem, but this code:
TroncalesViewCell *cell = [[TroncalesViewCell alloc]init];
cell = [tabla dequeueReusableCellWithIdentifier:CellIdentifier];
should be closer to this:
TroncalesViewCell *cell = [tabla dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[TroncalesViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
I think your existing code might return a nil cell, which would throw an exception. Right now you are pointlessly initializing a cell and then throwing it away and replacing it with another one.
From the crash log, it seems that the delegate of TroncalesViewController has been realloced when it should not be. You can check to make sure TroncalesViewController's delegate is still alive when you scroll the view.

NSMutableArray to UITableView

This could be a silly question but I am new to IPhone developing, anyhow I have an NSMutableArray with information loaded from a server. I am trying to put this information on a table. I searched around for some ideas on how to do this and I ran into this code which a lot of people seem to use in order to do this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [myArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"UITableViewCell"] autorelease];
}
cell.textLabel.text = [myArray objectAtIndex:[indexPath row]];
NSLog(#"Cell is %#", [myArray objectAtIndex:indexPath.row]);
return cell;
}
now my question is inside the if statement it gives me two errors with the autorelease saying: is unavailable and not available on reference counting mode, and arc forbids message send of autorelease, any thoughts?? thanks for the help
The code you have is older code and only works as-is with manual reference counting (MRC). Newer projects use automatic reference counting (ARC) by default. Just remove the call to autorelease and you will be fine.
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"UITableViewCell"];
You are using Automatic Reference Counting, which takes care of memory management for you (for the most part). Remove all references to manual memory management, such as autorelease (and retain, release, etc.), and the app will build. Use this here below:
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"UITableViewCell"];
}
This is also easily done using the freely available Sensible TableView framework. They have something called ArrayOfObjectsSection where you just pass the NSArray to and it will display it automatically, amongst many other stuff (including doning the server fetching for you).
This is a simple tutorial link for add a NSMutableArray into the tableView...Simple Tutorial link..Hope Its useful for you.

UITableView scrolling madness

I have a table view which gets data from a core data array. When I try to assign the value of the object "Post" to something or NSLog it the table scrolling lags.
Here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CellCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Post *post = [array objectAtIndex:indexPath.row];
// If I comment out the NSLog the scroll is smoothly
NSLog(#"%#", post.title);
// Same thing for the line below
cell.textLabel.text = post.title;
return cell;
}
EDIT:
I'm using StackMob v1.2.0
Using NSLog will surely cause performance issues, especially in methods like cellForRowAtIndexPath which is invoked frequently.
Please check these article for details :
Dropping NSLog in release builds
The Evolution of a Replacement for NSLog
EDIT :
Also your implementation causes the slowness.
You are missing the allocation of tableviewCells.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
First of all you should add the code that "Midhun MP" proposed.
If this doesnt help with the lagging problem...then i suppose post.title must be too heavy to be in that method (because that method gets called too many times)(Please let it not be that post.title uses internet connection to get the string?! Is it?)
Solution:
1)First thing in your app : Create an array2 and put in there all the post.title that u need(every time posts change you shoud update that array2)
2)use this array2 to get the text for the cells : cell.textLabel.textPost=[array2 objectAtIndex:indexPath.row];
3)I cant be 100% sure if NSLog is a problem because i havent tested that(could be..but this should only occur during debug...in release mode you shouldnt have it in there) but its easy to test and see(just comment the NSLog line)
Hope that helps.

dequeueReusableCellWithIdentifier does not work

I want to load around 6000 - 8000 rows in a UITableview. I get the data from the server using a async call and when I get the data I call
[tableView reloadData]
This is to refresh the table view . But because of some reason my app gets stuck and freezes .
When I debug , I found that cellforrowatindexpath is called 6000 times (on main thread) and
dequeueReusableCellWithIdentifier always returns null .
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CDTableRowCell *cell = nil;
// Create and Resue Custom ViewCell
static NSString *CellIdentifier = #"CellIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// got into render/theme objec
if(cell == nil){
cell = [[CDTableRowCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// MODIFYING CELL PROPERTIES HERE FROM AN ARRAY
// NO HTTP CALLS
}
Also, tableview starts reusing cell once I start scrolling but before that I never always create a new one.
Any clue why this strange behavior ???
try like this,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier =#"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
return cell;
}
The method in your question is not a table view datasource method. The datasource method has the table view as an argument. The method you have written is one that can be used to obtain a cell from the tableView itself, not to obtain a new cell from the datasource.
I don't know how often that method is called but overriding it is almost certainly not what you want to do.
I'm guessing you have subclassed a uitableview to be its own datasource? If so, you need to have the code in your question in the datasource method tableView:cellForRowAtIndexPath:, and not override the method as you have now.

Random UITable Delegate crash when selecting filled table

I am creating a simple app to select video urls out of a UITable. I have hooked my data source and delegate to a UIViewController subclass and the table is filled correctly. Also, it recognizes selections and prints to the log.
My issue is that it gets a "EXC_BAD_ACCESS" and crashes when I select a cell. I am looking through the code and the error propagates to this method:
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString* cellIdentifier = #"SelectionIdentifier";
//Errors start happening this next line
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}
//NSString* str = [[videos objectAtIndex:[indexPath row]] lastPathComponent];
NSString* test = #"test";
[[cell textLabel] setText:test];
return cell;
}
-(void) tableView:(UITableView*)myTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// NSLog(#"Selected!");
}
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {
return [videos count];
}
I'm not sure why this error is getting thrown in this method. Any fixes? I double checked to make sure the videos array wasn't nill.
I did another app that used this same method and it doesn't cause these errors.
Any help or suggestions would be greatly appreciated!
Instead of testing if(cell == nil) try using if(!cell). Honestly I'm not sure this is the issue, but after reviewing this I do not think that the error is not actually inside this method (it may somehow be related which is why it brings you here).
If this is only after you select a cell though, why is this method being called?
I think you should also call this method.Because this is preliminary delegate method
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
After seeing your tableView i am not finding any problem at all.Try that may be it will be solve.

Resources