UITableView reloadData crash - iphone

I added CustomImageView to the UITableViewCell.
UITableViewCell *cell = nil;
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell1"] autorelease];
}
CustomImageView *customIV = [[CustomImageView alloc] init];
[cell.contentView addSubView:customIV];
[customIV release];
But when I try to reload tableview, the error occurs.
error call stack is same as follows.
Output string is as follows.
-[CustomImageView superview]: message sent to deallocated instance 0x1f848f30

CustomImageView *customIV = [[CustomImageView alloc] initWithFrame:CGRectMake(x, y, w, h)];
[cell.contentView addSubView:customIV];
It's done with me when I've released memory.
So according to me, No need to release, because it'll deallocated memory.
Hopefully, it'll help you.Thanks.

Try to Comment this line[customIV release]; & run , it should not crash while reloading data.
The reason behind this is everytime it tries to create new custom view & releases it, so causes extra load on system & crash occurs.

You only want to add the image once to each cell. Change your code to this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell1"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell1"] autorelease];
CustomImageView *customIV = [[CustomImageView alloc] init];
[cell.contentView addSubView:customIV];
[customIV release];
}
return cell;
}
If this doesn't work then you need to show your complete cellForRowAtIndexPath method. By only showing part of your code you make it difficult to help.

This error occur because each time CustomImageView object created when your cell created.
so, best way is first initialize object of CustomImageView then create your UITableView
such like,
CustomImageView *customIV put it in your .h file and then #synthesize it in .m File
(put this code above UITableView)
self.customIV = [[CustomImageView alloc] init];
Then create UITableView
self.tablView = [[UITableView alloc]init];
.
.
.
.
And in cellForRowAtIndexPath only add [cell.contentView addSubView:self.customIV];

Related

iPhone:TableView cellForRowAtIndexPath method issue

I am facing a crashing problem in cellForRowAtIndexPath tableview delegate method
#interface EventListView : UIViewController <UITableViewDelegate, UITableViewDataSource>
IBOutlet UITableView *tblView;
NSMutableArray *arr_EventValues,*arr_Event_Details;
NSMutableArray *arr_EventListDetails;
#property(nonatomic, retain)NSMutableArray *arr_EventValues,*arr_EventListDetails, *arr_Event_Details;
#property(nonatomic, retain)UITableView *tblView;
- (void)viewDidLoad
{
appdelegate = (VibesGuideAppDelegate *)[[UIApplication sharedApplication] delegate];
ViewCalendar = [[CalendarView alloc] initWithNibName:#"CalendarView" bundle:[NSBundle mainBundle]];
[self.navigationController.navigationBar setHidden:YES];
self.arr_Event_Details = [[NSMutableArray alloc] init];
self.arr_EventValues = [[NSMutableArray alloc] init];
[super viewDidLoad];
}
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self.arr_EventListDetails count] > 0)
{
return [self.arr_EventListDetails count];
}
return 0;
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
// ------------------------------- Custom cell ------------------------------
Customcell *cell = (Customcell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[[Customcell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
cell.textLabel.text = #"Hello";
return cell;
}
* -[EventListView tableView:cellForRowAtIndexPath:]: message sent to deallocated instance 0x60e01b0 and I used tableview from xib and set all connections and also got arrayvalues in numberOfRowsInSection in method but in cellForRowAtIndexPath method is not called so please give me idea my issue....
Thanks in advance.
At first it seems your some variable gets released. Make sure you have properly allocated it. If you have declared #property for it you better use the variable as self.variable. You can use retain and in case of IOS 5 strong in property declaration.
Just to be sure you can track if any variable gets released via setting NSZombieEnabled to YES. With zombies enabled, messages to deallocated objects will no longer behave strangely or crash in difficult-to-understand ways, but will instead log a message and die in a predictable and debugger-breakpointable way. You can set NSZombieEnabled by the following steps.
Select Product from the menu bar above. Keep alt/option pressed and select "Test..." or "Run...". Go to the Arguments tab, and add NSZombieEnabled YES in the "Environment Variables" section.
Your tableview itself is already released - the error message says that you send the cellForRowAtIndexPath message to a deallocated instance of the table view - so your problem lies somewhere in not retaining or releasing the EventListView and cannot be seen in the code displayed here.
Check this one:
Table DataSource and delegate is set or not.
Used array in cellForRowAtIndexPath is properly set with property and synthesized as well used with self. name.
First of all you dequeue the cell and then create a new one. This is not a good practice, if you are able to dequeue a cell you should not create a new one. You should have something like this:
Customcell *cell = (Customcell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[[Customcell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
fix this and let me know if you are still running on the same problem.

UITableView and ViewDidLoad method

In my app I have a UITableViewCobtroller which creates the table view with checkmark accessory type. Table View loads and works correctly. In didSelectRowAtIndex method I wrote method of adding data in sqlite dataBase:
[self.dataBaseController openSettingsDB];
[self.dataBaseController updateRecordIntoTableNamed:kTableName withField:kSField1Name fieldValue:newCell.textLabel.text];
[self.dataBaseController closeDB];
It works well. So what I want is to retrieve the recorded data from dataBase and when the application is relaunched to select the row, that has the title, that I retrieved from sqlite dataBase.
I tried this:
-(void)viewDidLoad
{
NSArray *array = [[NSArray alloc] initWithObjects:
kCourse1, kCourse2, kCourse3, kCourse4, kCourse5, kCourse6, nil];
self.list = array;
[self.dataBaseController openSettingsDB];
[self.dataBaseController getRowFromTableNamed:kTableName whichRow:kSField1Name];
self.chosenStr = self.dataBaseController.dataString;
[lastIndexPath indexAtPosition:[array indexOfObjectIdenticalTo:self.chosenStr]];
UITableViewCell *cell = [[UITableViewCell alloc] init];
cell = [self.tableView cellForRowAtIndexPath:lastIndexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.tableView reloadData];
[array release];
[super viewDidLoad];
}
But it doesn't work. Please, suggest me any ideas. Thanks in advance.
Alick
Updated Answer:
You should not be doing this in viewdidLoad in the first place. Its a bad practice, you should do it in cellForRowAtIndexPath:.
More explaination:
The table is not loaded as of yet in viewDidLoad. You have to do [self.tableView reloadData]; before doing anything else. Doing that will call the delegate methods for table (it has no idea how many cells there are so getting the cell for any specfic index path doesn't make sense). See Table View Programming guide.
Also:
UITableViewCell *cell = [[UITableViewCell alloc] init];
cell = [self.tableView cellForRowAtIndexPath:lastIndexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
First, this is wrong. You are leaking memory with that alloc/init. Just do:
UITableViewCell *cell = nil;
cell = [self.tableView cellForRowAtIndexPath:lastIndexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
You need a call to UITableView's - scrollToRowAtIndexPath:atScrollPosition:animated: method. I would put this the viewDidAppear: method of your UITableViewController. See UITableView Class Reference.

Force UITableView to dump all reusable cells

I have a UITableView where I have the backgroud color set via
UIView *myView = [[UIView alloc] init];
if ((indexPath.row % 2) == 0)
myView.backgroundColor = [UIColor greenColor];
else
myView.backgroundColor = [UIColor whiteColor];
cell.backgroundView = myView;
[myView release];
The problem I find is that when I edit a table (via setEditing:YES...) some cells of the same color invariable are next to each other. How do I force UITableView to fully redraw. reloadData is not doing a great job.
Is there are deep-cleaning redraw?
I had this issue before so I'll share with you how I solved it:
You can use a boolean flag (say it's called needsRefresh) to control the behavior of cell creation in -cellForRowAtIndexPath:
An example:
- (UITableViewCell*) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath {
UITableViewCell *cell = [tableView dequeueResuableCellWithIdentifier:SOME_ID];
if(!cell || needsRefresh) {
cell = [[[UITableViewCell alloc] init....] autorelease];
}
//.....
return cell;
}
So, when you need a hard reload, set the needsRefresh flag to YES. Simple as a pimple.
For me the accepted answer didn't really work since I had no idea when to set the needsRefresh back to YES.
What worked for me was:
- (UITableViewCell*) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath {
UITableViewCell *cell = [tableView dequeueResuableCellWithIdentifier:customCellIdentifier];
if(nil == cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:customCellIdentifier];
}
//.....
return cell;
}
And then you change the customCellIdentifier value whenever you need to. This way the cells are also still reusable if you switch back to the original cell identifier.
The accepted method seems dirty, it just makes a bunch of new cells that are stored along with the bad ones. Here are a couple of solutions depending on your situation:
1.
first, for the situation described in the question you should not dump your cells and create new views on every cycle. You need to tag your view and then get it back when from the cell when you get a reuse cell:
- (UITableViewCell*) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath {
UITableViewCell *cell = [tableView dequeueResuableCellWithIdentifier:SOME_ID];
if(!cell) {
cell = [[UITableViewCell alloc] init];
UIView *myView = [[UIView alloc] init];
cell.backgroundView = myView;
[myView setTag:5]; //<------
}
UIView *myView = [cell viewWithTag:5]; //<------
if ((indexPath.row % 2) == 0)
myView.backgroundColor = [UIColor greenColor];
else
myView.backgroundColor = [UIColor whiteColor];
return cell;
}
//then just reload the tableview.
2.
...or even better, why not just use the cell backgrouncolor and update that without creating a view.
3.
A sure way to really clear out old cached cells it to simply recreate the UITableView object.
4.
In most cases you dont need to destroy these cells, just keep track of your elements and update them after getting the reusable cell.You can tag all your elements, keep a array reference to them, find them thought the view hierarchy... Im sure theres a bunch of other ways.
5.
heres a one liner to directly purge all cells, although not best practice to mess with the internals of objects like this as they might change in future versions:
[(NSMutableDictionary*)[tableview valueForKey:#"_reusableTableCells" ] removeAllObjects];
I was able to solve this by adding a refresh variable to the table datasource. I used a dictionary for each cell, but there's an extra key called #"refresh":#"1", indicating the cell needs refreshing. Once it's updated, I set that key's value to #"0". So whenever the table is reloaded, make sure the key goes back to #"0" again.
#define TABLE_VIEW_CELL_DEFAULT_ID #"cellIdentifier"
#property (nonatomic, strong) NSString *tableViewCellIdentifier;
#property (nonatomic) NSUInteger tableViewCellIdentifierCount;
// By using a different cell identifier, this effectively flushes the cell
// cache because the old cells will no longer be used.
- (void) flushTableViewCellCache
{
self.tableViewCellIdentifierCount++;
self.tableViewCellIdentifier = [NSString stringWithFormat:#"%#%i", TABLE_VIEW_CELL_DEFAULT_ID, self.tableViewCellIdentifierCount];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.tableViewCellIdentifier];
if (cell == nil) {
cell = [[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:self.tableViewCellIdentifier];
}
// rest of method...
}

Memory problem with basic UITableView when scrolling

I have a very simple UITableView that has 3 sections, and 3 rows per section.
#pragma mark -
#pragma mark UITableView delegate methods
- (NSInteger)tableView:(UITableView *)tblView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tblView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tblView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tblView
{
if (tblView == self.tableView) {
return 3;
}
else {
return 1;
}
}
Everything shows up fine, but as soon as I scroll my application crashes and my debugger tells me:
***** -[ProfileViewController tableView:cellForRowAtIndexPath:]: message sent to deallocated instance 0x5ae61b0**
I'm not exactly sure what I am doing wrong.
EDIT:
This is how I am displaying the ProfileViewController:
ProfileViewController* profileView = [[ProfileViewController alloc] initWithNibName:#"ProfileViewController" bundle:nil];
profileView.user_name = username;
profileView.message_source = messageSource;
[self.navigationController pushViewController:profileView animated:YES];
[profileView release];
Looks like your ProfileViewController instance is getting deallocated somehow. Make sure you're not calling its -autorelease after creating it.
Your code seems right. Your bug might be in your model or in the cell configuration. Turn on zombie support for search this kind of error.
something that helped me a similar problem was realizing the following: you may need to retain a table view controller by setting it up as an IBOutlet if it is a subview of another view - i.e. the parent must, in some way, be retaining the child.
Instead of using
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
please use
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
And change your implementation code as follow:
Don't use the below code in "cellForRowAtIndexPath" method. Instead use in "didSelectRowAtIndex" method.
In header(.h) file:
ProfileViewController* profileView;
In implementation (.m) file:
if(profileView==nil)
profileView = [[ProfileViewController alloc] initWithNibName:#"ProfileViewController" bundle:nil];
profileView.user_name = username;
profileView.message_source = messageSource;
[self.navigationController pushViewController:profileView animated:YES];

Customized UITableViewCell dissappears

I've seen a number of people having a similar issue, but either their solution did not help, or it was too different.
My problem is, I have a customized UITableViewCell, custom size, image and content. When I scroll up or down and then back again, the text within some of the cells disappears. This seems to be happening randomly.
I have read about the "dequeue"-issue but either I got it wrong or it doesnt fall into my case....
Anyways, heres the code for my Cells:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.imageView.image = [[UIImage alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:
[[shopItems objectAtIndex:indexPath.row] name] ofType:#"jpg"]];
UITextField *temp= [[UITextField alloc] initWithFrame:cell.frame];
temp.text = [[shopItems objectAtIndex:indexPath.row] name];
temp.textColor = [UIColor whiteColor];
temp.textAlignment = UITextAlignmentCenter;
UIImageView *cellView = [[UIImageView alloc] initWithImage:[[UIImage alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"smalltabs_wide_bg" ofType:#"png"]]];
[cellView addSubview:temp];
cell.backgroundView = cellView;
return cell;
}
Do you have any(!) ideas on this?
The possible problem is that you add UITextField and UIImageView to your cell each time you (re-)use the cell. Your code should look like
{
...
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// Insert all subviews to cell here
}
// setup cell's subviews here
...
}
And also mind all memory leaks in your code - when you create something with alloc, you must release it somewhere.
use reusableCell method
read this discussion
http://discussions.apple.com/thread.jspa?threadID=2075838&tstart=1035
One problem is that you are not releasing your temp UITextField, this will lead to a memory leak and could be causing the problems.
Sharing my experience:
Had similar problems. I have many tables in the app, and in one of them data would randomly disappear, and eventually the entire table would go away.
The problem for me was that I was dequeueing cells, giving all of them the same "unique" id. So several tables were sharing the same id, and I believe they were conflicting and messing up the cells I was looking at.
Giving each table it's own unique identifier solved the problem for me. (dah!)
(posted this here too, might be a duplicate : UITableView custom cell images disappear after scrolling.)