I've seen this problem with many others, went thru all the topics, but I can't seem to find a solution for it.
So I have a normal table view, with a cell linked to a .xib file, at first launch everything looks normal, but once I start scroll the app crashes immediately.
By enabling zombie objects I got to this error:
2012-05-03 16:18:13.008 coop_dev[27547:f803] * -[ActivityTableViewController tableView:cellForRowAtIndexPath:]: message sent to deallocated instance 0x6853990
But I'm not sure what to look for or what might go wrong:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
ItemCell *cell = (ItemCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ItemCell" owner:nil options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
Item *item = [self.activity objectAtIndex:indexPath.row];
[[cell projectLabel] setText:item.project];
[[cell descriptionLabel] setText:item.description];
[[cell timeLabel] setText:item.time];
[[cell timeAgoLabel] setText:item.timeAgo];
//cell.avatar = [UIImageView item.avatar];
cell.descriptionLabel.numberOfLines = 0;
[cell.descriptionLabel sizeToFit];
// remove the right arrow
cell.accessoryType = UITableViewCellAccessoryNone;
return cell;
}
It works fine at first launch but after that just crashes
EDIT
I re-created the problem in a new project, just a basic table with some data, once you start scrolling it crashes. Download: http://dl.dropbox.com/u/274185/TestTable.zip
In your FirstViewController.xib, remove the UITableViewController, but leave the UITableView. The crash happens because the File's Owner is already set as class FirstViewController in the Identity Inspector and it's like you have a second UITableViewController. Make sure also that the UITableView is hooked to the view outlet of the controller.
You are dequeueing code is a bit off... try mine:
UITableViewCell *cell = [[UITableViewCell alloc] init];
cell = nil;
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"cell"]
autorelease];
cell.imageView.image = nil;
cell.textLabel.text = nil;
}
Check your ItemCell class' dealloc method, you're probably overreleasing something.
Related
I was tasked to solve this bug in the app (It's for comercial use so I can't link the project). I'm also completely new to Objective-C or IOS development and I have no idea why the following happens. Reminder, I'm using custom cells.
When the tableview loads, everything looks fine.
Click here to see the example
But when I scroll up and back to the same postion the cell becomes blank, as if it had no data. Blank cell
If I repeat the same process everything looks fine again.
Here's the code for cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellId = #"cell2";
PedTableCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil)
{
cell = [(PedTableCell*)[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
if (tableView==_table3)
{
NSString *docsDirr;
NSString *documentsDirectoryForSaveImages;
docsDirr = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
documentsDirectoryForSaveImages = [docsDirr stringByAppendingPathComponent:#"/CarpetaImatges"];
NSString *match = #".jpg";
NSString *preCodigo;
NSScanner *scanner = [NSScanner scannerWithString:[pedarray objectAtIndex:indexPath.row]];
[scanner scanUpToString:match intoString:&preCodigo];
NSString *nomimg=[NSString stringWithFormat:#"%#.jpg", preCodigo];
UIImage *img = [UIImage imageWithContentsOfFile:[documentsDirectoryForSaveImages stringByAppendingPathComponent:nomimg]];
cell.img.image = img;
cell.layer.borderWidth=1.0f;
cell.img.layer.borderWidth=1.0f;
cell.cart.text = preCodigo;
cell.descart.text = [nomarray objectAtIndex:indexPath.row];
cell.cant.text = [cantarray objectAtIndex:indexPath.row];
cell.precart.text = [precioarray objectAtIndex:indexPath.row];
cell.pvpcart.text = [pvparray objectAtIndex:indexPath.row];
[cell layoutIfNeeded];
}
return cell;
}
I've debugged the method and everytime it returns a valid cell. When I click the empty cell it still works as expected. Essentially, the data is there, it's just not rendered for some reason.
I've checked other posts with the same/similar issue but nothing seems to really match. PrepareForReuse is a no go since there's no UI to be changed, just content. I'm getting the values of the arrays with indexPath.row to make sure I'm fetching the correct value. I've even tried to set the heightForRowAtIndexPath to the same height the cell should have (all cells are of the same size and never change) or let AutoLayout handle it but to no avail.
Code of numberOfRowsInSection (Returns the amount of orders that exists in database currently):
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if(tableView == _table3)
{
[self cargacarro];
return pedarray.count;
}
return pedarray.count;
}
Any ideas?
Register your cell nib in storyboard or in code before tableview is loaded, and after replace dequeueReusableCell... with this one
PedTableCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId forIndexPath:indexPath];
cell.img...
cell.cart...
remove this part, is no longer needed
if (cell == nil)
{
cell = [(PedTableCell*)[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
I have a subclass of UITableViewCell with a xib that I want to use as my table view cell. I need to modify the cell's properties on a cell by cell basis. Here is my code. The NSLog reveals that the properties are changed correctly, but when I run the app, the usernameLabel stays the same as the placeholder in the xib file. I'm grateful for any help and happy holidays.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"SimpleTableItem";
// ActivityCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
LiveCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
// Load the top-level objects from the custom cell XIB.
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"LiveCell" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [topLevelObjects objectAtIndex:0];
}
if (dataLoaded == YES) {
cell.usernameLabel = [[UILabel alloc] init];
NSLog(#"Data Cell Loaded");
PFObject *liveObject = [tableData objectAtIndex:indexPath.row];
cell.usernameLabel.text= liveObject[#"Name"];
NSLog(#"Name Label: %#", cell.usernameLabel.text);
return cell;
}
else {
return cell;
}
}
Consider this code:
cell.usernameLabel = [[UILabel alloc] init];
NSLog(#"Data Cell Loaded");
PFObject *liveObject = [tableData objectAtIndex:indexPath.row];
cell.usernameLabel.text= liveObject[#"Name"];
NSLog(#"Name Label: %#", cell.usernameLabel.text);
return cell;
You made a label and set its text, but so what? You never put it into the interface of the cell. So the label comes into existence, its text is set, and it then vanishes in a puff of smoke.
If the cell already has a usernameLabel in its interface, then it is wrong to replace it with this new one that is not in the interface. If it doesn't already have a usernameLabel, then you need to put this one in the interface. Either way, this code is silly.
I have a new project where I had to drag a prototype cell to a existing table view. I then
added some labels to the prototype cell with appropriate tags
set a identifier for the cell
and then in my tableview delegate when I get the delegate callback :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"myCustomCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UILabel *nameLabel = (UILabel *)[cell viewWithTag:11];
I see that nameLabel is nil. I have double checked and tripled checked the tag and reusable identifier with no luck. In the storyboard, I see that the tableview has the pro type cell as its cell with the contentView showing my labels. What am I missing?
Do you ever create a new cell in the if (cell == nil) branch? If yes, you are creating a regular UITAbleViewCell there. Do not expect any custom lable there, because you don't load it from any nib file nor from the storyboard.
Of what type is the cell object? NSLog it or have a look in the debugger which type is actually created.
You are allocating UITableViewCell which don't contain your custom label. If you have created a View using Storyboard then you should allocate that view using following method.
You can create a Utility method to get Class instance from NibName
+ (id)loadNibNamed:(NSString *)nibName ofClass:(Class)objClass
{
if (nibName && objClass)
{
NSArray *objects = [[NSBundle mainBundle] loadNibNamed:nibName
owner:nil
options:nil];
for (id currentObject in objects )
{
if ([currentObject isKindOfClass:objClass])
return currentObject;
}
}
return nil;
}
Use this in your code like
CustomViewCell *cell = (CustomViewCell *)[tableView dequeueReusableCellWithIdentifier:#"CustomViewCell"];
if (cell == nil)
{
cell = [Utility loadNibNamed:#"CustomViewCell" ofClass:[CustomViewCell class]];
}
cell.yourLabel.text = #"Dummy Text";
Hopefully this will help you.
Hello I'm having a little bit of trouble with something I'm working on. I have a static TableView with sections and I'm trying to get my text to be positioned in a certain spot so I have a ui label linked to a uitableviewcell. But for some reason It's not working. If you have any ideas on why I'm having trouble with this that would be great. I'm also a bit new to iOS development, just putting that out there.
TableViewController.m:
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell";
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[TableCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
int row = [indexPath row];
if (indexPath.section==0)
cell.textLabel.text = _1[row];
if (indexPath.section==1)
cell.textLabel.text = _2[row];
if (indexPath.section==2)
cell.textLabel.text = _3[row];
if (indexPath.section==3)
cell.textLabel.text = _4[row];
if (indexPath.section==4)
cell.textLabel.text = _5[row];
if (indexPath.section==5)
cell.textLabel.text = _6[row];
if (indexPath.section==6)
cell.textLabel.text = _7[row];
if (indexPath.section==7)
cell.textLabel.text = _8[row];
return cell;
}
- (BOOL)prefersStatusBarHidden
{
return YES;
}
#end
TableCell.h:
#import <UIKit/UIKit.h>
#interface TableCell : UITableViewCell
#property (strong,nonatomic) IBOutlet UILabel *TitleLabel;
#end
replace this line
cell.textLabel.text = _1[row];
with
cell.TitleLabel.text = _1[row];
this line is not needed anymore
if (cell == nil) {
cell = [[TableCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
in case TableCell is with xib, then you need to load it.
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// Load the top-level objects from the custom cell XIB.
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"TableCell" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [topLevelObjects objectAtIndex:0];
}
cell.TitleLabel.text = _1[row];
return cell;
you should check this
- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier
method to tell the table view how to create new cells. If a cell of the specified type is not currently in a reuse queue, the table view uses the provided information to create a new cell object automatically. if you previously registered a class or nib file with the same reuse identifier, the class you specify in the cellClass parameter replaces the old entry (Apple Document)
in your viewDidLoad method
[self.tableView registerClass:[TableCell class]
forCellReuseIdentifier:#"CellIdentifier"];
I have created a custom UITableViewCell with a UISwitch, a UIStepper and two labels inside.
When I run my app in the simulator, and the tableview lists each instance of this custom cell. I notice that when I toggle the switch in the first cell and increase it's stepper (affecting one label), the ninth cell is affected the same way.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *items = [self arrayForSection:indexPath.section];
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if(indexPath.section == 0){
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.notificationTitle.text = [items objectAtIndex:indexPath.row];
return cell;
}
I also have two sections in this tableview, and set the first one so that the selection style is off.
What is going on exactly and how to do I keep it from happening?
Where is the part where you are creating the custom cell? Are you doing that or is it just that you've missed it out while pasting it here?
Try this (hope you're using a NIB file to create a custom cell):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *questionTableIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:questionTableIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.notificationTitle.text = [items objectAtIndex:indexPath.row];
return cell;
}
When you use this [tableView dequeueReusableCellWithIdentifier:questionTableIdentifier]; you are actually reusing a already made instance of your cell(if there is any to be reused else create a new one). UITableViews work this way in order to conserve memory. If you have a very large number of cells it will still only consume about the same amount of memory as if there were only enough to cover the screen. In order to fix your problem you need to keep the state of your cell's some other place then the cell itself. Maybe a data structure in your tableviewcontroller or viewcontroller. And then set the values when your tableview wants to display the cell.
If you go with the non reusable cells then you could do something like this.
#property(nonatomic, strong)NSArray *cells;
- (id)init
{
self = [super init];
if ( self )
{
_cells = #[#[[[YourCell alloc] init],
[[YourCell alloc] init],
[[YourCell alloc] init]
],
[#[[YourCell alloc] init],
[[YourCell alloc] init],
[[YourCell alloc] init]]];
}
return self;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return _cells[indexPath.section][indexPath.row];
}
Assuming you have 2 sections with 3 cells in each section.