UITableView cell returning nil property values - iphone

I have the following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row==0)
{
static NSString *CellID = #"FlourishCustomCell";
FlourishCustomCell *cell = (FlourishCustomCell *) [tableView dequeueReusableCellWithIdentifier:CellID];
if (cell == nil) {
cell = [[[FlourishCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellID] autorelease];
cell.frame = CGRectMake(0, 0.0, 292.0, 30);
}
id <NSFetchedResultsSectionInfo> sectionInfo =
[[appDelegate.fetchedResultsController sections] objectAtIndex:indexPath.section];
NSLog(#"DATE:%#", [sectionInfo name]); //Output: March 25
cell.dateLabel.text=[sectionInfo name];
NSLog(#"header cell:%#", cell.dateLabel.text); //Output:header cell:(null)
return cell;
}
else {
static NSString *CellIdentifier = #"IdeaCustomCell";
IdeaCustomCell *cell = (IdeaCustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[IdeaCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.frame = CGRectMake(0, 0.0, 292.0, 70);
}
[self configureCell:cell atIndexPath:[self newIndexPathForIndexPath:indexPath]];
return cell;
}
}
The cells display and work fine for the else part (the IdeaCustomCell), but for some extremely frustrating reason, when I set the dateLabel of the FlourishCell, and then immediately try to access that value, I get a null value, even though I just set it! And the cell doesn't display on screen.
I tried overriding the setter method for dateLabel in the FlourishCustomCell class, and I put an NSLog statement there, but it never gets called for some reason.
I have absolutely no idea what could be causing this. I mean I'm allocating right then and there, but it's still giving me null. Any ideas?

You need to initialize the label
Solution 1: Initializing cell in code
#interface FlourishCustomCell : UITableViewCell
#property (nonatomic, retain) UILable * dateLabel;
#end
#implementation FlourishCustomCell
#synthesize dateLabel = _dateLabel;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])
{
_dateLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,0,300,50)];
[self.contentView addSubview:_dateLabel]
}
return self;
}
#end
Solution 2: Initializing cell from nib
#interface FlourishCustomCell : UITableViewCell
#property (nonatomic, retain) UILable * dateLabel;
#end
#implementation FlourishCustomCell
#synthesize dateLabel = _dateLabel;
- (id)init
{
self = [[[[NSBundle mainBundle] loadNibNamed:#"YOUR_NIB_NAME" owner:nil options:nil]
lastObject]
retain];
return self;
}
#end
EDIT: oops, forgot to return self on init method, updated the answer

i had the same problem when using nibs, this worked for me
- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = #"Cell";
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
NSString* nibFile = #"NibForCell";
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed: nibFile owner:nil options: nil];
cell = [topLevelObjects objectAtIndex: 0];
}
cell.cellText.text = #"test";
return cell;
}
just make sure you set the reuse identifier in the nib's properties

Related

Calling two different custom cell in one UITableView issue

I have created a custom cell FeatureCell which has 5 images in the row that will be called in the main view but when I call it I get empty row. So please where could be my problem?
I have googled about custom cell and I used the way that I have to use in the code below but nothing happen.
This is my FeatureCell.h
#interface FeatureCell : UITableViewCell{
IBOutlet UIImageView *img1;
IBOutlet UIImageView *img2;
}
#property (nonatomic, retain) UIImageView *img1;
#property (nonatomic, retain) UIImageView *img2;
#end
This is my FeatureCell.m
#implementation FeatureCell
#synthesize img,img1,img2,img3,img4;
#end
This is the my view-controller .m
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (section == 0) {
return [objectCollection count];
}
else{
return 1;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* cellIdentifier1 = #"FeatureCell";
FeatureCell *cell1 = (FeatureCell*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier1];
if (cell1 == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:cellIdentifier1 owner:nil options:nil];
cell1 = (FeatureCell*)[nib objectAtIndex:0];
}
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:CellIdentifier];
}
if ([indexPath section] == 0) {
containerObject = [objectCollection objectAtIndex:indexPath.row];
[[cell textLabel] setText:containerObject.store];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
else{
cell1.img1.image = [UIImage imageNamed:#"shower.png"];
cell1.img2.image = [UIImage imageNamed:#"parking.png"];
}
return cell;
}
You need to do something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:CellIdentifier];
}
containerObject = [objectCollection objectAtIndex:indexPath.row];
[[cell textLabel] setText:containerObject.store];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
} else {
static NSString* cellIdentifier1 = #"FeatureCell";
FeatureCell *cell1 = (FeatureCell*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier1];
if (cell1 == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:cellIdentifier1 owner:nil options:nil];
cell1 = (FeatureCell*)[nib objectAtIndex:0];
}
cell1.img1.image = [UIImage imageNamed:#"shower.png"];
cell1.img2.image = [UIImage imageNamed:#"parking.png"];
return cell1;
}
}
I might have the if condition backwards so double check that.
This implementation:
#implementation FeatureCell
#synthesize img,img1,img2,img3,img4;
#end
Results in a cell with some accessor methods but no initialised instances. You need to implement an init method to create the instances or connect the variables (which you define as outlets) to the associated XIB file. Read this guide.
I also agree with the comments about the structure of how you're creating your different cell instances. It's very disorganised and you seem to be mixing up references. You should split things out into different methods or at least put the code for creating the cells inside the if statements so you can't typo the cell instance names.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) //not indexPath.section...fixed my problem
{
static NSString *CellIdentifier = #"MenuHeadingCustomCell";
MenuHeadingCustomCell *cell =[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell ==nil)
{
cell = [[MenuHeadingCustomCell alloc]initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
return cell;
}
else
{
static NSString* cellIdentifier1 = #"LevelViewCell";
LevelViewCell *cell1 =[tableView dequeueReusableCellWithIdentifier:cellIdentifier1];
if (cell1 ==nil)
{
cell1 = [[LevelViewCell alloc]initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:cellIdentifier1];
// row counts which dictionary entry to load:
_Dictionary=[_array objectAtIndex:indexPath.row];
cell1.LevelTitleText.text =[NSString stringWithFormat:#"%#",[_Dictionary objectForKey:#"LevelLabelText"]];
cell1.LevelSubText.text =[NSString stringWithFormat:#"%#",[_Dictionary objectForKey:#"LevelLabelSubText"]];
cell1.LevelThumb.image =[UIImage imageNamed:[_Dictionary objectForKey:#"LevelLabelThumb"]];
}
return cell1;
}

NSUser Defaults save button status and display again

I am new to iphone development. I am developing an app in that i am displaying some contact name with uncheckmark image. Once user taps the button to selected means i am storing it in an nsuserdefaults. Here is the code what i have tried.Actually my problem is another user value will change dynamically.I am adding one boolean value for all the users who are coming in the tableview. If an one more person is added in the another user i want to show in off state. For other users i have to store the values stored in nsuserdefaults. First time i am manually looping 0 in total user.
My interface File
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITableViewDelegate,UITableViewDataSource>
NSArray * test;
IBOutlet UITableViewCell *customCell;
IBOutlet UIImageView *photo;
IBOutlet UILabel *userName;
NSMutableArray *dataArray;
NSMutableDictionary *tempDictionary;
NSMutableArray * selected;
NSUserDefaults *prefs;
NSMutableArray * statusArray;
NSMutableArray * prefsArray;
}
#property(nonatomic,retain) IBOutlet UITableViewCell *customCell;
#property(nonatomic,retain)IBOutlet UITableView *tblView;
#property(nonatomic,retain) NSMutableArray *dataArray;
#end
implementation file:
- (void)viewDidLoad
{
dataArray=[[NSMutableArray alloc]init];
selected=[[NSMutableArray alloc]init];
prefs=[NSUserDefaults standardUserDefaults];
prefsArray=[[NSMutableArray alloc]init];
NSMutableArray * anotheruser=[NSMutableArray arrayWithObjects:#"da",#"kn",#"gn",#"Prd",#"Kai",#"Sh",nil];
for (int i=0; i<anotheruser.count;i++) {
[selected addObject:[NSNumber numberWithInt:0]];
}
for (int i=0; i< anotheruser.count; i++) {
NSMutableDictionary *dict=[[NSMutableDictionary alloc]init];
[dict setValue:[anotheruser objectAtIndex:i] forKey:#"name"];
[dict setValue:[selected objectAtIndex:i] forKey:#"checked"];
[self.dataArray addObject:dict];
}
[super viewDidLoad];
}
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:NSInteger)section
{
return dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"MyViewCell" owner:self options:nil];
cell = customCell;
self.customCell = nil;
}
photo.image=[UIImage imageNamed:#"raj.jpg"];
NSMutableDictionary *item = [self.dataArray objectAtIndex:indexPath.row];
userName.text= [item objectForKey:#"name"];
[item setObject:cell forKey:#"cell"];
BOOL checked = [[item objectForKey:#"checked"] boolValue];
UIImage *image = (checked) ? [UIImage imageNamed:#"checked.png"] : [UIImage imageNamed:#"unchecked.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
button.frame = frame; // match the button's size with the image size
[button setBackgroundImage:image forState:UIControlStateNormal];
[button addTarget:self action:#selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
cell.backgroundColor = [UIColor clearColor];
cell.accessoryView = button;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self tableView: tblView accessoryButtonTappedForRowWithIndexPath: indexPath];
[self.tblView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)checkButtonTapped:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:tblView];
NSIndexPath *indexPath = [tblView indexPathForRowAtPoint: currentTouchPosition];
if (indexPath != nil)
{
[self tableView:tblView accessoryButtonTappedForRowWithIndexPath: indexPath];
}
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath: (NSIndexPath *)indexPath
{
NSMutableDictionary *item = [dataArray objectAtIndex:indexPath.row];
BOOL checked = [[item objectForKey:#"checked"] boolValue];
NSUInteger myInt=indexPath.row;
[item setObject:[NSNumber numberWithBool:!checked] forKey:#"checked"];
UITableViewCell *cell = [item objectForKey:#"cell"];
UIButton *button = (UIButton *)cell.accessoryView;
if (!checked)
{
[selected replaceObjectAtIndex:myInt withObject:[NSNumber numberWithInt:1]];
}else{
[selected replaceObjectAtIndex:myInt withObject:[NSNumber numberWithInt:0]];
}
[prefs setObject:selected forKey:#"status"];
NSLog(#"%#", selected);
UIImage *newImage = (checked) ? [UIImage imageNamed:#"unchecked.png"] : [UIImage imageNamed:#"checked.png"];
[button setBackgroundImage:newImage forState:UIControlStateNormal];
}
Just try with this code in cellForRowAtIndexPath: method
For CustomCell use like below..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyViewCell *cell = (MyViewCell *) [tableView dequeueReusableCellWithIdentifier:nil];
// MyCustomeCell *cell = (MyCustomeCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];//custom cell
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"MyViewCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (MyViewCell *) currentObject;
break;
}
}
}
and for DefaultCell use bellow code...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *kCustomCellID = #"MyCellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCustomCellID];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCustomCellID] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle=UITableViewCellSelectionStyleBlue;
}
}

Custom Cell Reuse Issue

I am loading a custom cell into a table view, and notice that my cell is not being re-used correctly. I am using a NSFetchedResultsController to pull the results from Core Data.
I am loading the cell from a nib. The cell identifier is setup in interface builder. The cells appear to get re-used because I am not creating a new cell everytime I scroll the table. However, the data is not being displayed correctly on the cells.
// BeerCell.h
#interface BeerCell : UITableViewCell
#property (nonatomic, strong) IBOutlet UIImageView *beerImage;
#property (nonatomic, strong) IBOutlet UILabel *displayBeerName;
#property (nonatomic, strong) IBOutlet UILabel *displayBeerType;
#end
// BeerCell.m
#implementation BeerCell
#synthesize beerImage;
#synthesize displayBeerName;
#synthesize displayBeerType;
#end
// Code where i'm setting up the cells for the tableView
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"BeerCell";
BeerCell *cell = (BeerCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"BeerCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (BeerCell *) currentObject;
break;
}
}
[self configureCell:cell atIndexPath:indexPath];
}
return cell;
}
- (void)configureCell:(BeerCell *)cell
atIndexPath:(NSIndexPath *)indexPath
{
Beer *beer = (Beer *) [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.displayBeerName.text = beer.name;
}
Take the configureCell function call outside the if block.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"BeerCell";
BeerCell *cell = (BeerCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"BeerCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (BeerCell *) currentObject;
break;
}
}
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}

UITableView crash on scroll

Whenever i scroll my UITableView, it looks at an array to find out what to fill the next cell with, but the array is empty, causing a crash, and appears to have been released somehow. Here is my code:
.h
#interface HomeViewController : UITableViewController {
NSArray *vaults;
}
#property (retain) NSArray *vaults;
#end
.m
#import "HomeViewController.h"
NSString *vaultsPath;
#implementation HomeViewController
#synthesize vaults;
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
vaultsPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Vaults"];
NSFileManager *fileManager = [NSFileManager defaultManager];
self.vaults = [fileManager contentsOfDirectoryAtPath:vaultsPath error:nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.vaults count];
}
- (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];
}
NSString *dictionaryPath = [NSString stringWithFormat:#"%#/%#",
vaultsPath,
[self.vaults objectAtIndex:indexPath.row]]; //Crashes at this line, with the self.vaults array now empty.
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:dictionaryPath];
cell = [AHCellCreation createCellWithDictionary:dictionary Cell:cell];
return cell;
}
- (void)dealloc
{
[super dealloc];
[self.vaults release];
}
#end
Any ideas?
My guess is the app crashes when you try to access the value of vaultsPath, which must be deallocated. Because the table view row count is based on the number of elements in the array, the method returning the cells, won't be called if there isn't any element in.
Try to retain the value assigned to vaultsPath, and don't forget to release it later.

How to copy pasteboard items into a table?

I have got an assignment here where I am supposed to
create an application, which copies the all the pasteboard items into
a table, that drills down into a detail view of said pasteboard item
.
Below, I give you my code of the RootViewController.m file. The program does not work and gives me an error of SIGABRT in this line cell.textLabel.text = cellValue;.
Could you tell me please, what could be possibly wrong here and thank you in advance.
#import "RootViewController.h"
#implementation RootViewController
#synthesize detailsViewController;
NSArray* pasteBoardItems;
- (void)viewDidLoad
{
// Get a reference to the system pasteboard
UIPasteboard* pasteBoard = [UIPasteboard generalPasteboard];
NSLog(#"%#", pasteBoard.items);
pasteBoardItems = [pasteBoard.items valueForKey:#"public.utf8-plain-text"];
pasteBoardItems = [pasteBoard.items valueForKey:#"public.item (kUTTypeItem)"];
self.navigationItem.title = #"Pasteboard";
[super viewDidLoad];
}
- (void)dealloc
{
[pasteBoardItems release];
[super dealloc];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [pasteBoardItems count];
}
// Customize the appearance of table view 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];
}
NSString *cellValue = [pasteBoardItems objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
// Configure the cell.
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
NSString *rowValue = [pasteBoardItems objectAtIndex:row];
NSString *message = [[NSString alloc] initWithFormat:#"You have selected \"%#\"",rowValue];
if(self.detailsViewController == nil){
DetailsViewController *d = [[DetailsViewController alloc] initWithNibName:#"DetailsViewController" bundle:[NSBundle mainBundle]];
self.detailsViewController = d;
[d release];
}
[self.detailsViewController initWithTextSelected:message];
[self.navigationController pushViewController:self.detailsViewController animated:YES];
}
#end
SIGABRT in most cases means that you want to access released object.
In your case, I suggest to add line [pasteBoardItems retain]; at the end of - (void)viewDidLoad method.