My custom cell gets messed up after being clicked? - iphone

Before: http://tinypic.com/view.php?pic=2j6a4h4&s=6
After: http://tinypic.com/view.php?pic=demxi&s=6
I have a problem with my cell's layout in the listView after being clicked. As you can see in the before and after pictures, the 3 labels in my cells (name, book, chapter) gets all messed up? What have I missed in my code? /Regards
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"BookmarkCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Bookmark *item = [self.items objectAtIndex:indexPath.row];
NSArray *chunks = [item.name componentsSeparatedByString: #","];
NSString *name;
NSString *book;
NSString *chapter;
if ([chunks count] > 0)
{
name = [chunks objectAtIndex:0];
if ([chunks count] > 1)
{
book = [chunks objectAtIndex:1];
if ([chunks count] > 2)
{
chapter = [chunks objectAtIndex:2];
}
}
}
UIView * pNewContentView= [[UIView alloc] initWithFrame:cell.contentView.bounds];
CGRect labelFrame= pNewContentView.bounds;
labelFrame.size.height= labelFrame.size.height * 0.5;
UILabel* pLabel1=[[UILabel alloc] initWithFrame:labelFrame];
[pNewContentView addSubview:pLabel1];
labelFrame.origin.y= labelFrame.size.height;
UILabel* pLabel2=[[UILabel alloc] initWithFrame:labelFrame];
[pNewContentView addSubview:pLabel2];
labelFrame.origin.y= labelFrame.origin.y + labelFrame.size.height;
UILabel* pLabel3=[[UILabel alloc] initWithFrame:labelFrame];
[pNewContentView addSubview:pLabel3];
[cell.contentView addSubview:pNewContentView];
[pLabel1 setText:(name)];
[pLabel2 setText:(book)];
[pLabel3 setText:(chapter)];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 70; // height of tableView Cell
}

Just expanding on what #onnoweb said and moving it to answer section as he's right:
What is happening is for every cell refresh, you are adding additional 3 labels to each cell causing a real bad memory hog. The paint issue is caused by new labels obscuring the old cause all labels have white BG by default.
You want to move the label creation code to where you initialize the newly created cell, but there is an issue with that where there is no elegant way to access added labels in already existing cells. My suggestion is for customized cells, such as this one, always create a customized subclass of UITableViewCell. (I personally think it's the most elegant approach):
for ex:
UIMyCustomTableViewCell.h
#interface UIMyCustomTableViewCell : UITableViewCell {
}
#property (nonatomic, retain) UILabel *label1;
#property (nonatomic, retain) UILabel *label2;
#property (nonatomic, retain) UILabel *label3;
#end
UIMyCustomTableViewCell.m
#implementation UIMyCustomTableViewCell
#synthesize label1 = _label1;
#synthesize label1 = _label2;
#synthesize label1 = _label3;
... init, memory cleanup, etc.
#end
At that point you can use that cell in your cellForRowAtIndexPath code:
if (cell == nil)
{
cell = [[UIMyCustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
CGRect labelFrame = cell.bounds;
labelFrame.size.height= labelFrame.size.height * 0.5;
cell.label1 = [[UILabel alloc] initWithFrame:labelFrame];
etc...
}
cell.label1.text = ...
cell.label2.text = ...
cell.label3.text = ...
I'm also a big fan of setting up look and feel of all customized cells in xib files instead of initializing labels in code like above, much cleaner in sizable apps.
Hope this helps.

Related

transform tableview

I want to images display for cell. but this code display, only white tableview.Why? Please tell me. (I use not storyboard.)
TableCell.h
#import <UIKit/UIKit.h>
#interface TableCell : UITableViewCell <UITableViewDelegate,UITableViewDataSource>
#property (nonatomic,retain) UITableView *tableCellView;
#property (nonatomic,retain) NSArray *cellArray;
-(NSString *)reuseIdentifier;
#end
TableCell.m
#import "TableCell.h"
#implementation TableCell
#synthesize tableCellView;
#synthesize cellArray;
-(NSString *)reuseIdentifier
{
return #"cell";
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [cellArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableCellView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
for (UIImageView *view in cell.subviews)
{
[view removeFromSuperview];
}
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 200, 200)];
imageView.image = [UIImage imageNamed:[cellArray objectAtIndex:indexPath.row]];
imageView.contentMode = UIViewContentModeCenter; // 画像サイズを合わせて貼る
CGAffineTransform rotateImage = CGAffineTransformMakeRotation(M_PI_2);
imageView.transform = rotateImage;
[cell addSubview:imageView];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 220;
}
#end
TableViewController.h
#import <UIKit/UIKit.h>
#class TableCell;
#interface TableViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
#property (nonatomic, retain) UITableView *tableView;
#property (nonatomic, retain) TableCell *tableViewCell;
#property (nonatomic, retain) NSArray *titlesArray;
#property (nonatomic, retain) NSArray *peopleArray;
#property (nonatomic, retain) NSArray *thingsArray;
#property (nonatomic, retain) NSArray *fruitsArray;
#property (nonatomic, retain) NSArray *arrays;
#end
TableViewController.m
#import "TableViewController.h"
#import "TableCell.h"
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize tableView;
#synthesize tableViewCell;
#synthesize titlesArray;
#synthesize peopleArray;
#synthesize thingsArray;
#synthesize fruitsArray;
#synthesize arrays;
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
tableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] bounds] style:UITableViewStylePlain];
[self.view addSubview:tableView];
titlesArray = [[NSArray alloc] initWithObjects:#"People", #"Things", #"Fruits", nil];
peopleArray = [[NSArray alloc] initWithObjects:#"Gardener.png", #"Plumber.png", #"BusinessWoman.png", #"BusinessMan.png", #"Chef.png", #"Doctor.png", nil];
thingsArray = [[NSArray alloc] initWithObjects:#"StopWatch.png", #"TrashCan.png", #"Key.png", #"Telephone.png", #"ChalkBoard.png", #"Bucket.png", nil];
fruitsArray = [[NSArray alloc] initWithObjects:#"Pineapple.png", #"Orange.png", #"Apple.png", nil];
arrays = [[NSArray alloc] initWithObjects:peopleArray, thingsArray, fruitsArray, nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [arrays count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [titlesArray objectAtIndex:section];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 220;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
TableCell *cell = (TableCell *)[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"TableViewCell" owner:self options:nil];
CGAffineTransform rotateTable = CGAffineTransformMakeRotation(-M_PI_2);
tableViewCell.tableCellView.transform = rotateTable;
tableViewCell.tableCellView.frame = CGRectMake(0, 0, tableViewCell.tableCellView.frame.size.width, tableViewCell.tableCellView.frame.size.height);
tableViewCell.cellArray = [arrays objectAtIndex:indexPath.section];
tableViewCell.tableCellView.allowsSelection = YES;
cell = tableViewCell;
}
return cell;
}
#end
AppDelegate.m
TableViewController *tvc = [[TableViewController alloc] init];
self.window.rootViewController = tvc;
UITableViewCell by default already has support for images. You do not need to to add a new UIImageView as a subview ...
So instead of this:
for (UIImageView *view in cell.subviews)
{
[view removeFromSuperview];
}
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 200, 200)];
imageView.image = [UIImage imageNamed:[cellArray objectAtIndex:indexPath.row]];
imageView.contentMode = UIViewContentModeCenter; // 画像サイズを合わせて貼る
CGAffineTransform rotateImage = CGAffineTransformMakeRotation(M_PI_2);
imageView.transform = rotateImage;
[cell addSubview:imageView];
Write this:
cell.imageView.image = [UIImage imageNamed:[cellArray objectAtIndex:indexPath.row]];
Oh, I now notice that LOTS OF OTHER STUFF is wrong with your code! Sorry to say that. Other stuff you need to change:
Copy this method from your TableCell to your TableViewController: - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath and remove the existing one
DELETE the TableCell class
I see you're also doing rotation... but leave that out for now. First try to make it work and THEN worry about rotation of the image.
Can I maybe advise you to read a book on iOS development? It seems as if you don't know what you're doing at all :(
But I do like to help you out. Can you maybe put all your code on http://www.github.com and invite me as a collaborator? My username is tomvanzummeren. I can make this app work for you.
your numberOfSectionsInTableView method might return 0. check the value of [arrays count]. And one more thing is you are not created UITableViewCell in proper way. That might be the problem too. Check this link for creating Custom UITableViewCell
Each UITableViewCell has an image support if it's style is default.
cell.imageView.image = yourImageView.image;
You don't need to do anything else.
You can change Image settings with changing yourImageView settings if you want.

Messy layout usint TTStyledTextLabel in TTTableViewCell

This is my first time using Three20 and I am trying to add a TTStyledTextLabel to my TTTableViewCell using the following code:
#interface ConvoreCell : TTTableViewCell{
TTStyledTextLabel * tt_title;
UITextView * title;
UILabel * detailed;
}
#property (nonatomic, retain) IBOutlet UITextView * title;
#property (nonatomic, retain) IBOutlet UILabel * detailed;
#property (nonatomic, retain) TTStyledTextLabel * tt_title;
#end
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
if (self == [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) {
// Initialization code
tt_title = [[TTStyledTextLabel alloc] init];
tt_title.font = [UIFont systemFontOfSize:15];
[self.contentView addSubview:tt_title];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect frame = tt_title.frame;
frame.size.width = 640;
frame.size.height = tt_title.text.height;
frame.origin.x = 45;
frame.origin.y = 5;
tt_title.frame = frame;
}
and in my TTTableView I have:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat titleHeight = [TTStyledText textFromXHTML:[[self.posts objectAtIndex:indexPath.row] message] lineBreaks:YES URLs:YES].height;
//NSLog(#"HEIGHT IS %f", titleHeight);
return titleHeight + 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ConvoreCell";
ConvoreCell *cell = (ConvoreCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[ConvoreCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
TTImageView * avatar = [[TTImageView alloc] initWithFrame:CGRectMake(cell.frame.origin.x+5, cell.frame.origin.y+5, 40, 40)];
avatar.urlPath = [[[self.posts objectAtIndex:indexPath.row] creator] img];
avatar.userInteractionEnabled = YES;
avatar.tag = indexPath.row;
[cell addSubview:avatar];
cell.tt_title.text = [TTStyledText textFromXHTML:[[self.posts objectAtIndex:indexPath.row] message] lineBreaks:YES URLs:YES];
}
However, the layout is messy as hell. Why is this?
I cannot find anything wrong with your code.
Looking at the image, what strikes me is that the last row which is correcly displayed contains a link.
What I suspect is that it could be some bug in TTStyledText, which in my experience is not really suitable for displaying full HTML.
Could you try and confirm (or dismiss) this hypothesis? Is always so that a url in a row will make it "go crazy"?
In any case, it will help to set a breakpoint on (or an NSLog after) the line
cell.tt_title.text = [TTStyledText textFromXHTML:[[self.posts objectAtIndex:indexPath.row] message] lineBreaks:YES URLs:YES];
and check what is going in cell.tt_title.text.

how to save the state in userdefaults of accessory checkmark-iphone

I am working on an application having UItableView. In the rows of the table i am able to put checkmarks.Now how to save the state of checkmarks so that even if user close the application
the state should be shaved and in the next launch of application checkmark should be shown.
i have followed the tutorials on NSUSerDefaults but Pulling my hairs where to put the codes of saving and retrieving.I have tried but every time errors are stuffing me and not able to fix.
My Code:
MY.h file
**#protocol LocationSelectionViewControllerDelegate <NSObject>
#required
- (void)rowSelected:(NSString *)selectedValue selectedIndex:(NSInteger)index;
#end**
#interface LocationSelection : UIViewController <UITableViewDelegate,UITableViewDataSource>{
UITableView *table;
***NSInteger selectedIndex;***
NSMutableArray *menuList;
***id <LocationSelectionViewControllerDelegate> delegate;***
}
#property (nonatomic,retain) NSMutableArray *menuList;
#property (nonatomic,retain) IBOutlet UITableView *table;
***#property (nonatomic, assign) id <LocationSelectionViewControllerDelegate> delegate;**
**#property NSInteger selectedIndex;***
#end
my .m file:
#implementation LocationSelection
***#synthesize menuList, table,selectedIndex,delegate;***
- (void)viewDidLoad
{
menuList = [[NSMutableArray alloc] initWithObjects:
[NSArray arrayWithObjects:#"LOCATION1", nil],
[NSArray arrayWithObjects:#"LOCATION2", nil],
[NSArray arrayWithObjects:#"LOCATION3", nil],
nil];
self.title = #"Location Selection";
[table reloadData];
[super viewDidLoad];
}
//MY CELLFORROWATINDEXPATH
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero] autorelease];
}
cell.highlighted = NO;
***NSArray * rowArray = [menuList objectAtIndex:indexPath.row];***
UILabel * nameLabel = [[[UILabel alloc] initWithFrame:CGRectMake(15, 8, 200, 20)] autorelease];
nameLabel.text = [NSString stringWithFormat:#"%#", [rowArray objectAtIndex:0]];
[cell.contentView addSubview:nameLabel];
***cell.accessoryType = (rowArray == selectedIndex && selectedIndex > -1 && selectedIndex < [menuList count]) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
***
}
//MY DIDSELECTROWATINDEXH
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int newRow = [indexPath row];
if (newRow != selectedIndex)
{
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
if (selectedIndex > - 1 && selectedIndex < [menuList count])
{
NSUInteger newIndex[] = {0, selectedIndex};
NSIndexPath *lastIndexPath = [[NSIndexPath alloc] initWithIndexes:newIndex length:2];
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath: lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
}
selectedIndex = newRow;
NSString *selectedValue=[menuList objectAtIndex:selectedIndex];
[self.delegate rowSelected:selectedValue selectedIndex:selectedIndex];
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
}
Use this method to save your data to NSUserDefaults
And set the data in viewDidLoad of LocationSelection
Hi I think it will suit you if you have an object(s) to indicate the checkmark. You can save this to the user defaults through synchronize. In the cellForRowATIndexPath: you can check if the value is present in the user defaults and if yes make the cell accessory as checkmarked and if its not present make it none.
Put a state in your menuList which reflects selection of the cell so even multiselection can be done easily. You can use a dictionary instead of the arrays. Arrays are fine but not as readable, so you have to remember which field contains what and map it to an index.
When the view loads load the menuList array from your userDefaults, when the app closes save the defaults.
In didSelectRowAtIndexPath you save selection in menuList.
In cellForRowAtIndexPath you read menuList and the new array index/dictionary key and set the checkmark.

Update selection from second UITableView in original UITableView

I can't get my first UITableView to update with a setting made in a second UITableView.
A user clicks a row in firstTableView causing secondTableView to be displayed. When the user selects a row, secondTableView disappears and firstTableView is reappears. However, the data isn't updated.
I tried using the following in firstTableView:
- (void) viewWillAppear:(BOOL)animated {
// (verified it's defenitely section 2, row 0 by logging it before and after...)
// (also verified that the source data has been updated before viewWillAppear is called...)
NSIndexPath *durPath = [NSIndexPath indexPathForRow:0 inSection:2];
NSArray *paths = [NSArray arrayWithObject:durPath];
[self.firstTableView reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationNone];
// If I use some row animation, I can clearly see that the correct row is being animated, it's just not being updated.
}
But the label does not update. Obviously I'm missing something.
Both views are modal view controllers.
Here's my cell construction:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [firstTableView dequeueReusableCellWithIdentifier:CellIdentifier];
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(150.0, 15.0, 120.0, 17.0)];
myLabel.backgroundColor = [UIColor clearColor];
myLabel.font = [UIFont systemFontOfSize:14];
myLabel.textAlignment = UITextAlignmentLeft;
static NSString* kConstants[] = {kOption0,kOption1,kOption2,kOption3,kOption4,kOption5,kOption6,kOption7,kOption8,kOption9,kOption10,nil};
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
if (indexPath.section == 2) {
[cell addSubview:myLabel];
}
}
switch (indexPath.section) {
case 0:
// … deal with a bunch of UISwitches
break;
case 1:
// … deal with section 1 stuff
break;
case 2:
{
NSLog(#"Verify that intType has in fact been changed here: %i, %#",intType, kConstants[intType]);
// Even though intType and the constant string reflects the correct (updated) values when returning from secondTableView, myLabel.text does not change, ie: it's correct one line above, but not correct one line below. The myLabel.text is just not updating to the new value.
myLabel.text = kConstants[intType];
cell.textLabel.text = #"Choose Some Value:";
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
break;
case 3:
// … deal with section 3 stuff
break;
}
[myLabel release];
return cell;
}
I have finally found the problem: when you reload the cell, (cell == nil) will be false, since the cell is already present.
Also, even if (cell == nil) is true, you are adding a new subview, and not modifying the existing one -- which is not only a memory management problem, it also makes the text unreadable by placing the labels on top of each other.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
static NSString* kConstants[] = {kOption0,kOption1,kOption2,kOption3,kOption4,kOption5,kOption6,kOption7,kOption8,kOption9,kOption10,nil};
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(150.0, 15.0, 120.0, 17.0)];
myLabel.backgroundColor = [UIColor clearColor];
myLabel.font = [UIFont systemFontOfSize:14];
myLabel.textAlignment = UITextAlignmentLeft;
myLabel.tag = 1;
myLabel.text = kConstants[intType];
[cell addSubview:myLabel];
[myLabel release];
cell.textLabel.text = #"Label";
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
} else {
UILabel *myLabel = (UILabel *)[cell viewWithTag:1];
myLabel.text = kConstants[intType];
}
return cell;
}
For anyone who stumbles upon this in the future, I'm posting a complete solution to my question here, thanks especially to Antal for showing me the major error in my table construction.
Using ViewWillAppear to reload the table is a bad idea in general, because it causes the table, or portions of the table to load twice. The proper way to do this is using the Delegate method of the second view controller, which I've done here.
I'm posting the relevant portions of the two view controllers. Both are setup as UViewControllers, not as UITableViewControllers. Both are modal views.
I hope someone finds this useful.
//
// FirstViewController.h
//
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#interface FirstViewController : UIViewController
<SecondViewControllerDelegate, UITableViewDataSource, UITableViewDelegate>
{
UITableView *firstTableView;
NSArray *myArray;
}
#property (nonatomic, retain) IBOutlet UITableView *firstTableView;
#property (nonatomic, assign) NSArray *myArray;
- (void) didSelectOptions:(NSInteger *)intOptionType;
- (void) didCancelOptions;
#end
//
// FirstViewController.m
//
#import "FirstViewController.h"
#import "Constants.h"
#implementation FirstViewController
#synthesize firstTableView;
#synthesize myArray;
- (void) viewDidLoad {
// Load the array that contains the option names, in this case, constants stored in Constants.h
myArray = [[NSArray alloc] initWithObjects:kStoredRowName0, kStoredRowName1, kStoredRowName2, nil];
}
// do everything else to deal with the first view . . .
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Use the indexPath.section as the identifier since objects in each section share unique construction, ie: switches, etc.
NSString *identifier = [NSString stringWithFormat: #"%d", [indexPath indexAtPosition: 0]];
// In this example I'm storing the important integer value in NSUserDefaults as kStoredConstant
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
UITableViewCell *cell = [firstTableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle: UITableViewCellStyleDefault
reuseIdentifier:identifier]
autorelease];
switch (indexPath.section) {
case 0: // OnOff Controls using UISwitch
NSLog(#"Section 0");
// set up switches …
break;
case 1: // Segmented Controls using UISegmentedControl
NSLog(#"Section 1");
// set up segmented controls …
break;
case 2: // Label that will be selected from SecondViewContoller
NSLog(#"Section 2");
// set up label
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(150.0, 15.0, 120.0, 17.0)];
myLabel.backgroundColor = [UIColor clearColor];
myLabel.font = [UIFont systemFontOfSize:14];
myLabel.textColor = [UIColor colorWithRed:0.25 green:0.0 blue:0.0 alpha:1.0];
myLabel.textAlignment = UITextAlignmentLeft;
myLabel.tag = indexPath.section;
myLabel.text = [myArray objectAtIndex:[userDefaults integerForKey:kStoredConstant]];
[cell addSubview:myLabel];
[myLabel release];
cell.textLabel.text = #"Choose A Value:";
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
break;
}
} else {
switch (indexPath.section) {
case 0: // OnOff Controls using UISwitch
NSLog(#"Section 0");
break;
case 1: // Segmented Controls using UISegmentedControl
NSLog(#"Section 1");
break;
case 2: // Label that will be selected from SecondViewContoller
{
NSLog(#"Section 2");
UILabel *myLabel = (UILabel *)[cell viewWithTag:indexPath.section];
myLabel.text = [myArray objectAtIndex:[userDefaults integerForKey:kStoredConstant]];
}
break;
}
}
// Format the cell label properties for all cells
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.font = [UIFont systemFontOfSize:14];
cell.textLabel.textColor = [UIColor colorWithRed:0.25 green:0.0 blue:0.0 alpha:1.0];
cell.textLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0];
return cell;
}
- (void) tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
// Un-highlight the selected cell
[firstTableView deselectRowAtIndexPath:indexPath animated:YES];
switch (indexPath.section) {
case 0: // Deal with changes in UISwitch Controls
NSLog(#"Section 0");
break;
case 1: // Deal with changes in Segmented Controls
NSLog(#"Section 1");
break;
case 2: // Launch the SecondViewContoller to select a value
{
SecondViewController *secondViewController = [[SecondViewController alloc] init];
secondViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
secondViewController.secondViewControllerDelegate = self;
[self presentModalViewController:secondViewController animated:YES];
[secondViewController release];
}
break;
}
}
#pragma mark -
#pragma mark SecondViewControllerDelegate
- (void) didSelectOptions:(NSInteger *)intOptionType {
// User selected a row in secondTableView on SecondViewController, store it in NSUserDefaults
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger:(int)intOptionType forKey:kStoredConstant];
[userDefaults synchronize];
// Reload only the row in firstTableView that has been changed, in this case, row 0 in section 2
[self.firstTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:2]]withRowAnimation:UITableViewRowAnimationNone];
[self dismissModalViewControllerAnimated:YES];
}
- (void) didCancelOptions {
// User didn't select a row, instead clicked a done or cancel button on SecondViewController
[self dismissModalViewControllerAnimated:YES];
}
// Make sure and release Array and Table
//
// SecondViewController.h
//
#import <UIKit/UIKit.h>
#protocol SecondViewControllerDelegate <NSObject>
- (void) didCancelOptions;
- (void) didSelectOptions:(NSInteger *)optionType;
#end
#interface SecondViewController : UIViewController
<UITableViewDataSource, UITableViewDelegate>
{
NSArray *myArray;
UITableView *secondTableView;
id secondViewControllerDelegate;
}
#property (nonatomic, retain) NSArray *myArray;
#property (nonatomic, retain) IBOutlet UITableView *secondTableView;
#property (nonatomic, assign) id<SecondViewControllerDelegate> secondViewControllerDelegate;
- (IBAction) doneViewingOptions:(id)sender; // This is wired to a Cancel or a Done Button
#end
//
// SecondViewController.m
//
#import "SecondViewController.h"
#import "Constants.h"
#implementation SecondViewController
#synthesize secondViewControllerDelegate;
#synthesize myArray;
#synthesize secondTableView;
- (void) viewDidLoad {
// Load the array that contains the option names, in this case, constants stored in Constants.h
myArray = [[NSArray alloc] initWithObjects:kStoredRowName0, kStoredRowName1, kStoredRowName2, nil];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Build a default table. This one is simple so the following is the only important part:
cell.textLabel.text = [myArray objectAtIndex:indexPath.row];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Return the changed row value to the FirstViewController using secondViewControllerDelegate
[self.secondViewControllerDelegate didSelectOptions:(NSInteger *)indexPath.row];
}
- (IBAction) doneViewingOptions:(id)sender {
// User didn't select a row, just clicked Done or Cancel button
[self.secondViewControllerDelegate didCancelOptions];
}
// Make sure and release Array and Table
You can use reloadRowsAtIndexPaths to reload a specific row (or rows) and avoid having to reload the entire table.
As for the label that displays the string value, could you post the code so we can see?

Custom UITableViewCells with a programmatically created table

When Ever I try to load data from an array into my table using custom cells it only shows the last cell like its overwriting all the cells until I Get to the end of the list. The table was created programmatically and when the cells don't load the blank table scrolls. If however I load the cells then only the last cell shows up and it won't scroll.
I figure I made a typo or something but I can't really see anything that would be of much help. The parser works and the array is fine its just that the cells are acting strange. I wanted to make it so that I had a fixed bar over the table as well but first I needed to get the custom cells to show up in the table and scroll properly
schedule.h
#interface Schedule : UIViewController <UITableViewDelegate, UITableViewDataSource> {
IBOutlet UITableView *newsTable;
UIActivityIndicatorView *activityIndicator;
CGSize cellSize;
NSXMLParser *fileParser;
NSMutableArray * events;
NSMutableArray * announcements;
NSMutableDictionary * item;
NSString *currentElement;
NSMutableString * currentTitle, * currentDate, * currentSummary, * currentId, * curr entTime, *currentContent;
UITableViewCell *appCell;
}
#property(nonatomic, retain)IBOutlet UITableView *newsTable;
#property(nonatomic, retain)IBOutlet UITableViewCell *appCell;
-(void)parseXMLFileAtURL:(NSString *)URL;
#end
schedule.m
- (void)loadView{
UITableView *tableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]
style:UITableViewStylePlain];
tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
tableView.delegate = self;
tableView.dataSource = self;
tableView.tag = 4;
[tableView reloadData];
self.view = tableView;
[tableView release];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [events count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = appCell;
self.appCell = nil;
}
// Configure the cell.
UILabel *label;
label = (UILabel *)[cell viewWithTag:1];
int eventIndex = [indexPath indexAtPosition: [indexPath length] - 1];
label.text = [[events objectAtIndex: eventIndex] objectForKey: #"event"];
return cell;
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
NSLog(#"webpage parsed");
NSLog(#"events array has %d items", [events count]);
newsTable = (UITableView*)[self.view viewWithTag:4];
[newsTable reloadData];
}
I added more code the problem may be somewhere else.
I think your problem is that the cell is being released. When you call self.appCell = nil;, the object will be released and the variable set to nil. Try changing cell = appCell; to cell = [[appCell retain] autorelease]; so that the cell is retained long enough for the table view to retain it again.
Also, you could change int eventIndex = [indexPath indexAtPosition: [indexPath length] - 1]; to int eventIndex = indexPath.row;. The row and section properties were added to NSIndexPath specifically for use in UITableView, and it is guaranteed that the index path passed to cellForRowAtIndexPath: will contain exactly two indices.
try with following code;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = #"CellIdentifier";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; // CustomCell is the class for standardCell
if (cell == nil)
{
NSArray *objectList = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
for (id currentObject in objectList) {
if([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (CustomCell*)currentObject;
break;
}
}
cell.label.text = [[events objectAtIndex: indexPath.row] objectForKey: #"event"];
}
return cell;
}
when you load the xib file with NSBundle, it will return an array of Bundle. Then you have to check it and then use it.
If you tried like;
NSString *memberName; // member variable
NSString *name = memberName;
memberName = nil;
// the member variable "memberName, giving the reference to name;
//So if you set memberName as nil, name also become a nil value.
// You have to use like;
name = [memberName retain];
memberName = nil;
Try to learn more about iPhone development documents.
Click here for Documentation.
Click here for sample code.
I think it will help you.