Xcode how to link UITableView Cells to a new View Controller - iphone

I currently have developed a Tabbed Based Application. The first Tab is decors which displays Colour Swatches or Images in a TableView Structure. Currently when you push on a image or Colour swatch An alert pops up saying which table cell you have pushed. I instead want to link each table cell image or Colour swatch to a new view controller showing a bigger image of that image or colour swatch. A modal would also do fine
#import "TableViewsViewController.h"
#implementation TableViewsViewController
#pragma mark -
#pragma mark Synthesizers
#synthesize table;
#synthesize sitesArray;
#synthesize imagesArray;
#pragma mark -
#pragma mark View lifecycle
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
// Load up the sitesArray with a dummy array : sites
NSArray *sites = [[NSArray alloc] initWithObjects:#"a", #"b", #"c", #"d", #"e", #"f", #"g", #"h", nil];
self.sitesArray = sites;
[sites release];
UIImage *active = [UIImage imageNamed:#"a.png"];
UIImage *ae = [UIImage imageNamed:#"b.png"];
UIImage *audio = [UIImage imageNamed:#"c.png"];
UIImage *mobile = [UIImage imageNamed:#"d.png"];
UIImage *net = [UIImage imageNamed:#"e.png"];
UIImage *photo = [UIImage imageNamed:#"f.png"];
UIImage *psd = [UIImage imageNamed:#"g.png"];
UIImage *vector = [UIImage imageNamed:#"h.png"];
NSArray *images = [[NSArray alloc] initWithObjects: active, ae, audio, mobile, net, photo, psd, vector, nil];
self.imagesArray = images;
[images release];
[super viewDidLoad];
}
#pragma mark -
#pragma mark Table View datasource methods
// Required Methods
// Return the number of rows in a section
-(NSInteger) tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
return [sitesArray count];
}
// Returns cell to render for each row
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure cell
NSUInteger row = [indexPath row];
// Sets the text for the cell
//cell.textLabel.text = [sitesArray objectAtIndex:row];
// Sets the imageview for the cell
cell.imageView.image = [imagesArray objectAtIndex:row];
// Sets the accessory for the cell
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// Sets the detailtext for the cell (subtitle)
//cell.detailTextLabel.text = [NSString stringWithFormat:#"This is row: %i", row + 1];
return cell;
}
// Optional
// Returns the number of section in a table view
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
#pragma mark -
#pragma mark Table View delegate methods
// Return the height for each cell
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 78;
}
// Sets the title for header in the tableview
-(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return #"Decors";
}
// Sets the title for footer
-(NSString *) tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
return #"Decors";
}
// Sets the indentation for rows
-(NSInteger) tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 0;
}
// This method is run when the user taps the row in the tableview
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Tapped row!"
message:[NSString stringWithFormat:#"You tapped: %#", [sitesArray objectAtIndex:indexPath.row]]
delegate:nil
cancelButtonTitle:#"Yes, I did!"
otherButtonTitles:nil];
[alert show];
[alert release];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
NSLog(#"Memory Warning!");
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
self.table = nil;
self.sitesArray = nil;
self.imagesArray = nil;
[super viewDidUnload];
}
- (void)dealloc {
[table release];
[sitesArray release];
[imagesArray release];
[super dealloc];
}
#end
Part where the Alert is
// This method is run when the user taps the row in the tableview
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Tapped row!"
message:[NSString stringWithFormat:#"You tapped: %#", [sitesArray objectAtIndex:indexPath.row]]
delegate:nil
cancelButtonTitle:#"Yes, I did!"
otherButtonTitles:nil];
[alert show];
[alert release];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

In didSelectRowAtIndexPath you can just init another view controller and present. You can present it from self.navigationController so that there is a back button if you wish. Here I show it presented modally:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Deselect row
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Declare the view controller
UIViewController *anotherVC = nil;
// Determine the row/section on the tapped cell
switch (indexPath.section) {
case 0:
switch (indexPath.row) {
case 0: {
// initialize and allocate a specific view controller for section 0 row 0
anotherVC = [[ViewControllerForRowZeroSectionZero alloc] init];
break;
}
case 1: {
// initialize and allocate a specific view controller for section 0 row 1
anotherVC = [[ViewControllerForRowOneSectionZero alloc] init];
break;
}
}
break;
case 1: {
// initialize and allocate a specific view controller for section 1 ALL rows
anotherVC = [[ViewControllerForAllRowsSectionOne alloc] init];
break;
}
}
// Get cell textLabel string to use in new view controller title
NSString *cellTitleText = [[[tableView cellForRowAtIndexPath:indexPath] textLabel] text];
// Get object at the tapped cell index from table data source array to display in title
id tappedObj = [sitesArray objectAtIndex:indexPath.row];
// Set title indicating what row/section was tapped
[anotherVC setTitle:[NSString stringWithFormat:#"You tapped section: %d - row: %d - Cell Text: %# - Sites: %#", indexPath.section, indexPath.row, cellTitleText, tappedObj]];
// present it modally (not necessary, but sometimes looks better then pushing it onto the stack - depending on your App)
[anotherVC setModalPresentationStyle:UIModalPresentationFormSheet];
// Have the transition do a horizontal flip - my personal fav
[anotherVC setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
// The method `presentModalViewController:animated:` is depreciated in iOS 6 so use `presentViewController:animated:completion:` instead.
[self.navigationController presentViewController:anotherVC animated:YES completion:NULL];
// We are done with the view controller. It is retained by self.navigationController so we can release it (if not using ARC)
[anotherVC release], anotherVC = nil;
}

You're 90% of the way there! In didSelectRowAtIndexPath, instead of putting up the alert, instantiate and set up the view controller whose view you want to show and call presentViewController:animated:.
See my book: http://www.apeth.com/iOSBook/ch19.html#_presented_view_controller

Are u using Storyboard?
If so, you can build a segue, set it to Modal or Push. Pointing from the TableView to the destination ViewController
Then name it with an identifier in the segue's inspector.
Then in didSelectRowAtIndexPath, call performSegue: withIdentifier
You can also setup the destination ViewController based on the cell selected in prepareForSegue.
Hope it helps.

Related

how i can add UIActivityIndicator on UITableView

i want to attech UIActivityIndicator with UITableView when then first time table load on iphone activity must start blinking and when the table compleletely load in iphone when i click on load more cell then also i want to show activity blink for that moment when more rows loading kindly tell me how can i do that this is the code if you complete this code by your self then thanks in advance
#import "RootViewController.h"
#import "Tweet.h"
#implementation RootViewController
#synthesize customImage,pagecontrol,cell;//indexPath;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad
{
pageSize = 2;
// totalpages =(NSInteger) (xmlParser.tweets)/5 ;
xmlParser = [[XMLParser alloc] loadXMLByURL:#"http://api.twitter.com/1/statuses/user_timeline/KentFranks.xml"];
[super viewDidLoad];
self.title = #"Tweets";
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if([xmlParser.tweets count]>pageSize)
{
return pageSize+1;
}
return xmlParser.tweets.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
//UIImage *twitterLogo = [[UIImage imageNamed:#"twitter-logo.png"]autorelease];
NSString *imagepath = [[NSBundle mainBundle] pathForResource:#"twitter-logo" ofType:#"png"];
UIImage *image =[[ UIImage alloc] initWithContentsOfFile:imagepath];
cell.imageView.image = image;
cell.detailTextLabel.text= #"Add Subtitle here";
Tweet *currentTweet = [[xmlParser tweets] objectAtIndex:indexPath.row];
if(indexPath.row<pageSize)
{
cell.textLabel.text = currentTweet.content;
}
else
{
cell.textLabel.text = #"Load more ";
}
NSLog(#"cell: %#",cell);
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
-(IBAction)loadmorebutton:(id)sender;
{
NSIndexPath *currentPath = [self.tableView indexPathForSelectedRow];
NSIndexPath *nextPath = [NSIndexPath indexPathForRow:currentPath.row+1 inSection:currentPath.section];
[self.tableView selectRowAtIndexPath:nextPath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row==pageSize)
{
pageSize=pageSize+2;
[tableView reloadData];
}
}
/*
-(IBAction)pagecontrol:(UIPageControl *)pageControl
{
[self.tableView reloadData];
}
-(IBAction)Pageindexchanges:(id)sender
{
NSLog(#"clicked page index: %i ",pagecontrol.currentPage);
}
*/
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 55;
}
#pragma mark -
#pragma mark Table view delegate
/*- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
*/
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload
{
}
- (void)dealloc
{
[xmlParser release];
[super dealloc];
}
#end
Try this code may be helped you...
Add the spinner directly to the cell view felt a little hacky, so I used a 1x1 transparent png as the image view and resized it to be whatever my spinner size is:
UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"NoReuse"] autorelease];
cell.textLabel.text = #"Loading...";
UIActivityIndicatorView *spinner = [[[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray] autorelease];
// Spacer is a 1x1 transparent png
UIImage *spacer = [UIImage imageNamed:#"spacer"];
UIGraphicsBeginImageContext(spinner.frame.size);
[spacer drawInRect:CGRectMake(0,0,spinner.frame.size.width,spinner.frame.size.height)];
UIImage* resizedSpacer = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
cell.imageView.image = resizedSpacer;
[cell.imageView addSubview:spinner];
[spinner startAnimating];
return cell;
That gives a cell that looks like this:
This May Help you
https://github.com/pothibo/PHRefreshTriggerView
And second one option is
https://github.com/enormego/EGOTableViewPullRefresh

Select UITableView's row when clicking on UISwitch

I have a UITableView with UISwitchs on them.
When the switch is toggled I want to run a function. The function just logs If the switch is on or off and the row that the switch has been changed on. The problem that im having is that when I click on the switch it does not log the correct row unless I have clicked on that row before clicking the switch.
I guess my problem is that clicking the switch does not select the row. How can I make it so that it either selects the row or can I add the ID to the switch?
So switch ID "1" is "ON".
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"POICell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//set the cell text to the catName
cell.textLabel.text = [self.catNames objectAtIndex:[indexPath row]];
//add switch
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = switchView;
[switchView setOn:YES animated:NO];
[switchView addTarget:self action:#selector(switchChanged: ) forControlEvents:UIControlEventValueChanged];
// Configure the cell...
return cell;
}
- (void) switchChanged:(id)sender {
NSString *StrCatID =[[NSString alloc]init];
StrCatID = [self.catIDs objectAtIndex:[self.inputTableView indexPathForSelectedRow].row];
UISwitch* switchControl = sender;
NSLog( #"The switch for item %# is %#",StrCatID, switchControl.on ? #"ON" : #"OFF" );
}
To find the cell that holds the switch
UISwitch *switchInCell = (UISwitch *)sender;
UITableViewCell * cell = (UITableViewCell*) swithInCell.superview;
To find the indexpath of that cell
NSIndexPath * indexpath = [myTableView indexPathForCell:cell]
In your case
- (void) switchChanged:(id)sender {
UISwitch *switchInCell = (UISwitch *)sender;
UITableViewCell * cell = (UITableViewCell*) swithInCell.superview;
NSIndexPath * indexpath = [myTableView indexPathForCell:cell]
NSString *strCatID =[[NSString alloc]init];
strCatID = [self.catIDs objectAtIndex:indexpath];
NSLog( #"The switch for item %# is %#",StrCatID, switchInCell.on ? #"ON" : #"OFF" );
}
You should set the IndexPath.row as a Tag to each Switch in cellForRowAtIndexPath Method
switchView.tag= indexPath.row;
And when switch value change .you'll get the Row number
- (void) switchChanged:(UISwitch *)sender {
int rowIndex =[sender tag];
//rowIndex you may use it further as you wanted.
}
You can retrieve the NSIndexPath for the UISwitch that was changed in the tableview. This is the same idea for any control as already answered in this post : Detecting which UIButton was pressed in a UITableView
- (void) switchChanged:(id)sender
{
CGPoint switchPositionPoint = [sender convertPoint:CGPointZero toView:[self tableView]];
NSIndexPath *indexPath = [[self tableView] indexPathForRowAtPoint:switchPositionPoint];
}
This will work for iOS7, previously I used [sender superview] but that now returns a UITableViewCellContentView inside of a UITableViewCellScrollView.
I had to do double mySwitch.superview.superview to get the proper cell.
Here's an example
- (void)switchToggle:(UISwitch *)mySwitch
{
UITableViewCell *cell = (UITableViewCell *)mySwitch.superview.superview;
NSIndexPath *indexpath = [self.tableView indexPathForCell:cell];
NSLog(#"toggle section %d rowID %d", indexpath.section, indexpath.row);
}
I think the problem is that you use dequeueReusableCellWithIdentifier, and all of your cell has the same id.
A better way to do this is determine which cell the sender is in.
- (UITableViewCell *)findCellForView:(UIView *)view
{
for (; view != nil; view = view.superview)
if ([view isKindOfClass:[UITableViewCell class]])
return view;
return nil;
}
Once you have this method. then it's a matter of replacing [self.inputTableView indexPathForSelectedRow] with
UITableViewCell *cell = [self findCellForView:sender];
NSIndexPath *indexPath = [self.inputTableView indexPathForCell:cell];
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
#property (retain, nonatomic) IBOutlet UITableView *tableview;
#end
#interface ViewController ()
{
NSMutableArray *arr;
UITableViewCell* aCell;
UISwitch *myswitch;
}
#import "ViewController.h"
#interface ViewController ()
{
NSMutableArray *arr;
UITableViewCell* aCell;
UISwitch *myswitch;
}
#end
#implementation ViewController
#synthesize tableview;
- (void)viewDidLoad
{
[super viewDidLoad];
arr = [[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"5", nil];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
return [arr count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
aCell = [tableview dequeueReusableCellWithIdentifier:#"SwitchCell"];
if( aCell == nil )
{
aCell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"SwitchCell"];
aCell.textLabel.text = [arr objectAtIndex:indexPath.row];
myswitch = [[UISwitch alloc]initWithFrame:CGRectZero];
aCell.accessoryView = myswitch;
[myswitch setOn:YES animated:YES];
}
switch (indexPath.row)
{
case 0:
{
[myswitch addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
}
break;
case 1:
{
[myswitch addTarget:self action:#selector(switchChanged1:) forControlEvents:UIControlEventValueChanged];
}
break;
}
return aCell;
}
- (void) switchChanged:(id)sender {
UISwitch *aswitch = sender;
if (aswitch.on==YES) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"hello" message:#"okfine" delegate:self cancelButtonTitle:#"done" otherButtonTitles:nil, nil];
[alert show];
}
else
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"no1" message:#"notfine" delegate:self cancelButtonTitle:#"Returnback" otherButtonTitles:nil, nil];
[alert show];
}
}
- (void) switchChanged1:(id)sender {
UISwitch *aswitch1 = sender;
if (aswitch1.on==YES) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"second" message:#"okfine" delegate:self cancelButtonTitle:#"done" otherButtonTitles:nil, nil];
[alert show];
}
else
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"no2" message:#"notfine" delegate:self cancelButtonTitle:#"Returnback" otherButtonTitles:nil, nil];
[alert show];
}
}
- (void)dealloc {
[tableview release];
[super dealloc];
}
#end

How to create UITableView and detail view separately

I've created an app using single view based.Now I have to display 15 number of menus and description about each menu.So I thought of using UITableView inserting in that.While selecting a cell it should display long text & image content.Do i have to create each ViewController for each description or any shortcuts to add description programmatically
Here is my code for table view
- (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];
}
// Set up the cell...
cell.textLabel.font = [UIFont fontWithName:#"Helvetica" size:15];
cell.textLabel.text = [NSString stringWithFormat:#"Cell Row #%d", [indexPath row]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// open a alert with an OK and cancel button
NSString *alertString = [NSString stringWithFormat:#"Clicked on row #%d", [indexPath row]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertString message:#"" delegate:self cancelButtonTitle:#"Done" otherButtonTitles:nil];
[alert show];
[alert release];
}
This is for creating UIAlertView when cell is touched.
How can i do for long text and image display.Any ideas pls.
I think you can use a navigation controller and push tableView on it. On selection of a cell of table you should push a detailView (one detail view for all cells). This works only if you have to show same format of details data in the detailView. Else if you have to different screens for each selection, then you can design all those screens which will also make it heavy.
You can create a single ViewController wich initialize with image and text, inside view controller you should create UITextView and UIImageView. ViewController must be something like this:
#interface ViewController : UIViewController {
UIImageView *imageView;
UITextView *textView;
}
-(id)initWithText:(NSString *)text image:(UIImage *)image;
#end
#implementation ViewController
-(id)initWithText:(NSString *)text image:(UIImage *)image {
if (self = [super init]) {
//ImageView initialization
imageView.image = image;
//TextViewInitialization
textView.text = text;
}
return self;
}
#end
In view controller where table view you can create 2 arrays with corresponding images and text to cells.
Then didSelectRowAtIndexPath: must looks like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ViewController *vc = [[ViewController alloc]initWithText:[textArray objectAtIndex:indexPath.row] image:[imagesArray objectAtIndex:indexPath.row]];
[[self navigationController] pushViewController:vc animated:YES];
[vc release];
}

Table view cell disappear when i switch to another page and then back

I have a table view that you can add and delete cells. I can enter multiple cells and when i go to the next page and then switch back, all of my entries/ cells are erased. Can any one figure this out? Here is my code:
#implementation FacePlatesViewController
#synthesize woodGrain;
#synthesize nav, array;
#synthesize EditButton;
#synthesize myTableView, image;
#synthesize cell, string1;
#synthesize myDic, cells, defaults;
#synthesize selectedCell, currentChosenFund;
- (void)viewDidLoad {
[super viewDidLoad];
NSString * myFile = [[NSBundle mainBundle]pathForResource:#"cells" ofType:#"plist"];
self.myTableView.backgroundColor = [UIColor clearColor];
cells = [[NSMutableArray alloc]initWithContentsOfFile:myFile];
}
- (void)addObject:(id)anObject
{
if (anObject != nil)
{
[cells addObject:anObject];
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.myTableView reloadData];
}
- (IBAction)editButton:(id)sender
{
if (self.editing)
{
[self setEditing:NO animated:YES];
[self.myTableView setEditing:NO animated:YES];
}
else
{
[self setEditing:YES animated:YES];
[self.myTableView setEditing:YES animated:YES];
}
}
- (void)add
{
MyDetailViewController * detail = [[MyDetailViewController alloc]init];
detail.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:detail animated:YES];
[detail.text becomeFirstResponder];
[detail release];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [cells count];
}
- (void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[[self cells] removeObjectAtIndex:[indexPath row]];
NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
[[self myTableView] deleteRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:CellIdentifier] autorelease];
}
//The if block should end here. You should set the cell's label irrespective whether the cell was nil. This is the cause of the issue you are facing.
cell.textLabel.text = [[cells objectAtIndex:indexPath.row] valueForKey:#"name"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
FirstFolderViewController * first = [[FirstFolderViewController alloc]init];
first.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:first animated:YES];
[first release];
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toIndexPath:(NSIndexPath *)targetIndexPath
{
NSUInteger sourceIndex = [sourceIndexPath row];
NSUInteger targetIndex = [targetIndexPath row];
if (sourceIndex != targetIndex)
{
[[self cells] exchangeObjectAtIndex:sourceIndex
withObjectAtIndex:targetIndex];
}
}
- (void)dealloc
{
[woodGrain release];
[myTableView release];
[EditButton release];
[nav release];
[cells release];
[myTableView release];
[myDic release];
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
}
*/
- (void)viewDidUnload
{
[self setWoodGrain:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
Thanks :D
Actually even unloading of the view will be enough to throw away the cells. Try this in your viewDidLoad:
if(!cells) {
NSString * myFile = [[NSBundle mainBundle]pathForResource:#"cells" ofType:#"plist"];
self.myTableView.backgroundColor = [UIColor clearColor];
cells = [[NSMutableArray alloc]initWithContentsOfFile:myFile];
}
(this way you won't be rereading the array every time the view is loaded).
And if you want the added cells to persist between app restarts, you do need to save them somewhere. You can't change the files in the main bundle, but you can write your own file into the Caches folder, which you can get via:
[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
Write your file into that folder and read the cells from there instead of the main bundle. If you have some pre-defined cells in the main bundle file, you can check if the file in the Caches folder exists when the app starts, and if not, copy the bundle's file into the Caches folder.
Edit: if you do presentModalViewController to get back from the another page, you'll get a fresh copy of FacePlatesViewController, which obviously loads the default cells from the file.
Instead, you should add a "delegate" property to your FirstFolderViewController:
#property(nonatomic, assign) id delegate; //yes, assign, not retain
then when presenting FirstFolderViewController do:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
FirstFolderViewController * first = [[FirstFolderViewController alloc]init];
first.delegate = self;
first.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:first animated:YES];
[first release];
}
Then add a method to FacePlatesViewController:
- (void) onDoneWithFirstFolderViewController //you can come up with a better name
{
[self dismissModalViewControllerAnimated:YES];
}
and in your FirstFolderViewController, when you are ready to close it, do:
if([delegate respondsToSelector:#selector(onDoneWithFirstFolderViewController)])
[delegate onDoneWithFirstFolderViewController];
Ironically, if you had implemented the cell persistence in a file, this issue might have been unnoticed (because each new FacePlatesViewController would load an up-to-date cell list), but you would have had a memory leak each time you went between pages.
To me, the problem seems to be related to your code in ViewWillAppear: Have you ensured that your cells array is fine when you call [self.myTableView reloadData]; ?
Also, I noticed myTableView. Are you subclassing UITableViewController or implementing table delegates? If you are subclassing, the table view reference is named tableView.
HTH,
Akshay

Grouped Table View Obj-C

I followed the tutorial here and was wondering how to make the table appear grouped.
ex:
group1 contains Subview One and Subview Two
group2 contains Subview Three
I switched the type in interface builder but that only shows one group.
Thanks,
Adam
Sidenote* I am a completely new at objective c, hence the tutorial.
EDIT
I thought it might be helpful to put up the piece of code
#import "RootViewController.h"
#import "SubViewOneController.h"
#import "SubViewTwoController.h"
#implementation RootViewController
#pragma mark -
#pragma mark View lifecycle
-(void)awakeFromNib {
views = [[NSMutableArray alloc] init];
SubViewOneController *subViewOneController = [[SubViewOneController alloc] init];
SubViewTwoController *subViewTwoController = [[SubViewTwoController alloc] init];
//Subview 1
subViewOneController.title = #"Subview One";
[views addObject:[NSDictionary dictionaryWithObjectsAndKeys:
#"Subview One", #"title",
subViewOneController, #"controller",
nil]];
[subViewOneController release];
//Subview 2
subViewOneController = [[SubViewOneController alloc] init];
subViewOneController.title = #"Subview Two";
[views addObject:[NSDictionary dictionaryWithObjectsAndKeys:
#"Subview Two", #"title",
subViewTwoController, #"controller",
nil]];
[subViewOneController release];
//Subview 3
subViewOneController = [[SubViewOneController alloc] init];
subViewOneController.title = #"Subview Three";
[views addObject:[NSDictionary dictionaryWithObjectsAndKeys:
#"Subview Three", #"title",
subViewOneController, #"controller",
nil]];
[subViewOneController release];
UIBarButtonItem *temporaryBarButtonItem = [[UIBarButtonItem alloc] init];
temporaryBarButtonItem.title = #"Back";
self.navigationItem.backBarButtonItem = temporaryBarButtonItem;
[temporaryBarButtonItem release];
self.title = #"Basic Navigation";
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [views count];
}
//
//I think it goes somewhere in here
//
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewStyleGrouped reuseIdentifier:CellIdentifier];
}
cell.text = [[views objectAtIndex:indexPath.row] objectForKey:#"title"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIViewController *targetViewController = [[views objectAtIndex:indexPath.row] objectForKey:#"controller"];
[[self navigationController] pushViewController:targetViewController animated:YES];
}
- (void)dealloc {
[views dealloc];
[super dealloc];
}
#end
Ok so you are correct it does go into your cellForRowAtIndexPath: you will be looking to do something like:
if ([indexPath section] == 0) {
//stuff for first section.
}
if ([indexPath section] == 1) {
//stuff for second section.
}
You will need to also deal with how your are configuring the cell from your array. The sections row numbers start with 0. The same thing with didSelectRowAtIndexPath:
If you don't deal with the section where you set the cell.text you will end up with
Subview One
Subview Two
Subview One
I recommend getting the iPhone Programming (The Big Nerd Ranch Guide)
In Interface Builder, choose your UITableView object and choose Grouped as the style.
If you are programmatically creating it, use the initWithStyle: UITableViewStyleGrouped.
EDIT:
if (section == 0) { /* your first section */ }
if (section == 1) { /* your second section */ }
This is all controlled by your UITableViewDataSource. The numberOfSectionsInTableView: method controls how many groups there are, and tableView:numberOfRowsInSection: controls how many rows are in each group.
Your tableView:cellForRowAtIndexPath: on the UITableViewDelegate gets an NSIndexPath object; indexPath.section tells you which group and indexPath.row tells you which row in the group. The cell you return really has no idea which group it is in or which row in the group it is, it's all controlled by the fact that you return it for a particular indexPath when tableView:cellForRowAtIndexPath: is called.