I am trying to pass an object to a static grouped table view that I have created in story board.
Here is the code that I am using in my first view to push the second view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Row Selected");
CustomerDetailTableViewController *detailView = [[self storyboard] instantiateViewControllerWithIdentifier:#"DetailsView"];
detailView.customer = [self.fetchedResultsController objectAtIndexPath:[self.tableView indexPathForSelectedRow]];
NSLog(#"%#",detailView.customer.firstName);
[self.navigationController pushViewController:detailView animated:YES];
}
The NSlog for the firstName is correct but when the detail view is pushed the cells in the detailView are null. I'm probably just missing something dumb but a fresh set of eyes would be much appreciated.
Here is the code for the detailView controller:
CustomerDetailTableViewController.h
#class Customer;
#import <UIKit/UIKit.h>
#interface CustomerDetailTableViewController : UITableViewController{
Customer *customer;
UILabel *fullName;
UILabel *address;
UILabel *homePhone;
UILabel *cellPhone;
UILabel *email;
}
#property (nonatomic, strong) IBOutlet UILabel *fullName;
#property (nonatomic, strong) IBOutlet UILabel *address;
#property (nonatomic, strong) IBOutlet UILabel *homePhone;
#property (nonatomic, strong) IBOutlet UILabel *cellPhone;
#property (nonatomic, strong) IBOutlet UILabel *email;
#property (nonatomic, strong) Customer *customer;
#end
CustomerDetailTableViewController.m
#import "CustomerDetailTableViewController.h"
#import "Customer.h"
#implementation CustomerDetailTableViewController
#synthesize fullName, address, homePhone, cellPhone, email, customer;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
fullName = [NSString stringWithFormat:#"%# %#", customer.firstName, customer.lastName];
address = [NSString stringWithFormat: #"%#/n%#, %# %#", customer.address, customer.city, customer.state, customer.zipCode];
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
So, you have created the two views (the first TableView and the CustomerDetailTableViewController) with storyboards?
In that case, you have to click on the connection line between the two views into the storyboard and set the "Identifier" field, into the section "Storyboard Segue", to something like "setCustomer". Here's a screenshot:
Here a little screenshot:
After that, you can comment the method tableView:didSelectRowAtIndexPath: on the first TableView, and replace with this method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"setCustomer"]) {
CustomerDetailTableViewController *customerDetailVC = (CustomerDetailTableViewController *)[segue destinationViewController];
customerDetailVC.customer = [self.fetchedResultsController objectAtIndexPath:[self.tableView indexPathForSelectedRow]];
}
}
Remember to include
#include "CustomerDetailTableViewController.h"
at the top of implementation file.
I hope this help!
Related
I need a little help here, I've loaded a view by modal and basically I'm now trying to dismiss this view now but it keep crashing after the view goes.
It says * -[PointInfoController endAppearanceTransition]: message sent to deallocated instance 0x74d5e90
Below is the .H file:
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#class PointInfoController;
#protocol PointInfoDelegate
- (void)PointInfoDidFinish:(PointInfoController*)PointInfoController;
#end
#interface PointInfoController : UIViewController <UIScrollViewDelegate>
{
IBOutlet UIScrollView *scrollView;
IBOutlet UIImageView *thumbnailView;
IBOutlet UIButton *Dismiss;
id<PointInfoDelegate> delegate;
}
#property (retain) id<PointInfoDelegate> delegate;
#property (retain, nonatomic) IBOutlet UITextView *description;
#property (retain, nonatomic) IBOutlet UIScrollView *scrollView;
#property (retain, nonatomic) IBOutlet UIImageView *thumbnailView;
- (IBAction)DismissView:(id)sender;
#end
Below is the .M file:
#import "PointInfoController.h"
#import "LockOnLocation.h"
#implementation UIScrollView (AutoContentSize)
- (void) setAutosizeContent:(BOOL)autosizeContent {
if (autosizeContent) {
CGFloat contentWidth =
self.frame.size.width == self.superview.frame.size.width ?
self.superview.frame.size.width :
self.frame.size.width + 10;
CGFloat contentHeight =
self.frame.size.height == self.superview.frame.size.height ?
self.superview.frame.size.height :
self.frame.size.height + 164;
self.contentSize = CGSizeMake(contentWidth, contentHeight);
}
}
#end
#implementation PointInfoController
#synthesize description;
#synthesize scrollView;
#synthesize thumbnailView;
#synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
self.scrollView.delegate = self;
[super viewDidLoad];
}
- (void)viewDidUnload
{
[self setDescription:nil];
[scrollView release];
scrollView = nil;
[self setScrollView:nil];
[self setThumbnailView:nil];
[thumbnailView release];
thumbnailView = nil;
[Dismiss release];
Dismiss = nil;
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (IBAction)DismissView:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
[self release];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)dealloc {
[description release];
[scrollView release];
[thumbnailView release];
[Dismiss release];
[super dealloc];
}
#end
I'm new to all this and I spent quite a few days on the same problem. Blamed everything but myself! I discovered I was inadvertently release(ing) the instance referred to. In my case I had put the instance into a SSLConnectionRef and CFRelease'd it. I'm not sure why you are having the issue looking at your code. In any event, I thought your compiler would complain about your [instance release] methods, since these are no longer allowed. You are having the problem because both you and the system are releasing the instance. You need to get rid of your release and all will be well.
I have a plist (array of dictionaries) which populates a table view and works properly. I use Xcode 4 with storyboards.
Now I've created a detail view from a regular UIViewController and of course I want the selected name to be displayed in the nameLabel in the detail view. But I can't make the right connection. This is my code so far:
WineObject.m:
#import "WineObject.h"
#implementation WineObject
#synthesize libraryContent, libraryPlist;
- (id)initWithLibraryName:(NSString *)libraryName {
if (self = [super init]) {
libraryPlist = libraryName;
libraryContent = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:libraryPlist ofType:#"plist"]];
}
return self;
}
- (NSDictionary *)libraryItemAtIndex:(int)index {
return (libraryContent != nil && [libraryContent count] > 0 && index < [libraryContent count])
? [libraryContent objectAtIndex:index]
: nil;
}
- (int)libraryCount {
return (libraryContent != nil) ? [libraryContent count] : 0;
}
- (void) dealloc {
if (libraryContent) [libraryContent release];
[super dealloc];
}
#end
ViewController.h:
#import <UIKit/UIKit.h>
#class WineObject;
#interface WinesViewController : UITableViewController {
WineObject *wine;
}
#end
ViewController.m:
#import "WinesViewController.h"
#import "WineObject.h"
#import "WineCell.h"
#interface WinesViewController ()
#end
#implementation WinesViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (void)viewWillAppear:(BOOL)animated {
wine = [[WineObject alloc] initWithLibraryName:#"Wine"];
self.title = #"Vinene";
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [wine libraryCount];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"wineCell";
WineCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
cell.nameLabel.text = [[wine libraryItemAtIndex:indexPath.row] valueForKey:#"Name"];
cell.districtLabel.text = [[wine libraryItemAtIndex:indexPath.row] valueForKey:#"District"];
cell.countryLabel.text = [[wine libraryItemAtIndex:indexPath.row] valueForKey:#"Country"];
cell.bottleImageView.image = [UIImage imageNamed:[[wine libraryItemAtIndex:indexPath.row] valueForKey:#"Image"]];
cell.flagImageView.image = [UIImage imageNamed:[[wine libraryItemAtIndex:indexPath.row] valueForKey:#"Flag"]];
cell.fyldeImageView.image = [UIImage imageNamed:[[wine libraryItemAtIndex:indexPath.row] valueForKey:#"Fylde"]];
cell.friskhetImageView.image = [UIImage imageNamed:[[wine libraryItemAtIndex:indexPath.row] valueForKey:#"Friskhet"]];
cell.garvesyreImageView.image = [UIImage imageNamed:[[wine libraryItemAtIndex:indexPath.row] valueForKey:#"Garvesyre"]];
return cell;
}
#pragma mark - Table view delegate
#end
WineCell.h:
#import <UIKit/UIKit.h>
#interface WineCell : UITableViewCell
#property (nonatomic, strong) IBOutlet UILabel *nameLabel;
#property (nonatomic, strong) IBOutlet UILabel *districtLabel;
#property (nonatomic, strong) IBOutlet UILabel *countryLabel;
#property (nonatomic, strong) IBOutlet UIImageView *bottleImageView;
#property (nonatomic, strong) IBOutlet UIImageView *flagImageView;
#property (nonatomic, strong) IBOutlet UIImageView *fyldeImageView;
#property (nonatomic, strong) IBOutlet UIImageView *friskhetImageView;
#property (nonatomic, strong) IBOutlet UIImageView *garvesyreImageView;
#end
Are you using a XIB for interface or generating it programmatically?
If you are using a XIB, the issue is that you aren't loading it up:
Change
winesDetailViewController = [[WinesDetailViewController alloc] init];
To
winesDetailViewController = [[WinesDetailViewController alloc] initWithNibName:#"YourNibNameHere" bundle:nil];
Or, if you are generating it programmatically, you must first set nameLabel or it will be nil. #synthesize doesn't set the variable, it simply generates getters and setters so that you can set it from outside.
Inside your viewDidAppear: (or better yet inside your init) add:
self.nameLabel=[[UILabel alloc] initWithFrame:CGRectMake(100,100,100,100)];
EDIT: If you are using Storyboards, it appears that you have to do the following.
Storyboards are all about relationships. Inside the story board editor, you add buttons and tell them which view controller they connect to. The same idea applies to TableView Cells. You can add a prototype table view cell (and customize it) and assign a relationship to it. The relationship you will want to give it is your detail view.
1.) Subclass UITableViewCell and give it a property that is the dictionary that you are trying to send to the detail view
2.) When creating cells (cellForRowAtIndexPath:) you will need to make sure to dequeue your custom cell and assign your dictionary to the property that you gave it.
3.) Make sure that your detail view has the identifier: DetailView
4.) Inside the table view controller, add the following code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"DetailView"])
{
//This works because by the time prepareForSeque: is called, the navigationController has loaded the new view
((DetailView *)[[self.navigationController viewControllers] objectAtIndex:0]).dataProperty=((MyCustomTableViewCell *)sender).dataProperty;
}
}
That ought to do it!
I try to save numbers from a textfield on one viewController in a NSMutableArray when I press a button on this viewContoller. (this is working now)
Then i want the numbers give out on a textview which is on a secondViewController but this dont work. When i want to give out the array on the first Viewcontroller it work fine.
Also i cant erase the NSMutableArray with a button on the SecondviewController.
The SecondviewController have the same class like the viewController.
Can someone show me how i can give out an array on a seconviewcontroller?
Hallo,
at the moment i have this:
//ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
NSMutableArray *textViewArray;
}
#property (strong, nonatomic) IBOutlet UITextField *textLable2;
#property (strong, nonatomic) IBOutlet UITextField *textLable1;
- (IBAction)setArrayWithCurrentNumber:(id)sender;
- (IBAction)returnToTextfield:(id)sender;
#end
//this the .m file:
#import "ViewController.h"
#implementation ViewController
#synthesize textLable2;
#synthesize textLable1;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
textViewArray = [[NSMutableArray alloc]init];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setTextLable2:nil];
[self setTextLable1:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (IBAction)setArrayWithCurrentNumber:(id)sender
{
NSString *string1 = self.textLable1.text;
[textViewArray addObject:string1];
NSMutableArray *array = [NSMutableArray arrayWithArray:textViewArray];
NSString *string2 = [array componentsJoinedByString:#" "];
self.textLable2.text = [NSString stringWithString:string2];
NSLog(#"%#",textViewArray);
}
- (IBAction)returnToTextfield:(id)sender
{
[textLable1 resignFirstResponder];
[textLable2 resignFirstResponder];
}
#end
If you're calling the second view controller from the first one you could set a property on the second one to hold the NSMutableArray or just send it on the initializer.
something like:
- (id)initWithArray:(NSMutableArray *)array {
if (self = [super init]) {
myArray = [array copy];
}
return self;
}
assuming your second view controller has declared NSMutableArray * myArray;
Edit: Adding some more code in here...
// I'll assume you use some kind of UINavigationController to show your content
- (void)showSecondViewController {
SecondViewController * vc = [[[SecondViewController alloc] initWithArray:yourMutableArray] autorelease];
[self.navigationController pushViewController:vc];
}
Hi I have two viewControllers.
NewsViewController
#import "SingleViewController.h"
#interface NewsViewController : UIViewController {
}
- (NSString *)getFirstImage:(NSString *)htmlString;
#end
and the implementation file:
#import "SingleViewController.h"
SingleViewController *singleViewController;
#interface NewsPadViewController () <UIActionSheetDelegate>
- (void)loadSubscriptions;
#property (nonatomic, assign) BOOL wrap;
#property (nonatomic, retain) NSMutableArray *items;
#end
#implementation NewsPadViewController
....CODE....
- (void)carouselCurrentItemTapped{
//[self addSubview:articolo];
MWFeedItem *item =[reader.feedItems objectAtIndex:[carousel currentItemIndex]];
NSLog(#"Current Item tappped, index: %d", [carousel currentItemIndex]);
singleViewController.prova.text=#"CIAO";
singleViewController.ciao=#"sample";
[singleViewController.web loadHTMLString:item.summary baseURL:nil];
NSLog(#"conternutio:");
NSLog(singleViewController.ciao);
}
SingleViewController.h
#import <UIKit/UIKit.h>
#interface SingleViewController : UIViewController{
#public
UIWebView *web;
UILabel *prova;
NSString *ciao;
}
#property (nonatomic,retain) IBOutlet UIWebView *web;
#property (nonatomic,retain) IBOutlet UILabel *prova;
#property (nonatomic,retain) IBOutlet NSString *ciao;
#end
and SingleViewController.m
#import "SingleViewController.h"
#implementation SingleViewController
#synthesize web,prova,ciao;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[prova setText:ciao];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[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
Why I can't access from NewsPadViewController at object in SingleViewController? Where is my error? thanks
UPADATE
- (void)carouselCurrentItemTapped{
//[self addSubview:articolo];
MWFeedItem *item =[reader.feedItems objectAtIndex:[carousel currentItemIndex]];
NSLog(#"Current Item tappped, index: %d", [carousel currentItemIndex]);
SingleViewController *singleViewController = [[SingleViewController alloc] initWithNibName:#"SingleViewController" bundle:[NSBundle mainBundle]];
singleViewController.prova.text=#"CIAO";
singleViewController.ciao=#"sample";
[singleViewController.web loadHTMLString:item.summary baseURL:nil];
NSLog(#"conternutio:");
NSLog(singleViewController.ciao);
[singleViewController setOpz:#"sample"];
}
I don't see any instantiation of SingleViewController. You have a pointer to it, but I don't see anywhere in your code example where you actually create it.
Somewhere you need something like:
if (!singleViewController) {
singleViewController = [[SingleViewController alloc] init];
}
or
SingleViewController *singleViewController = [[SingleViewController alloc] initWithNibName:#"SingleView" bundle:nil];
or from somewhere else you need to send a message or set an instance variable in NewsViewController that points to an existing instance of SingleViewController.
I am actually very surprised how difficult it is to keep your code well structured and readable when doing iphone app stuff... but it might be because I am doing something wrong.
I have a Sign Up page containing different kinds of inline-editable data: birthday, gender, name, password, phone number. I have made the page as a table view of custom cells where each cell is an instance of a sub class of UITableViewCell and is read from its own nib file. This because I thought that I then might be able to reuse these different kinds of cells later in other table view pages.
The approach of encapsulating the different custom cells in their own place is not working that well though:
Who is going to be the controller of e.g the gender picker inside the GenderCell?
How am I actually going to reuse the cells in a different table view controller when I had to put the SignUpController as the file's owner of the cell nib files?
I do not know if anyone but myself understood what I just wrote, but if so, I would be very thankful for any suggestions on how to structure my code differently.
Thanks a lot,
Stine
To make things more clear (?!) let me paste some of my code in here:
EditableLabel.h
#interface EditableLabel : UILabel {
UIView *inputView, *inputAccessoryView;
}
#property (nonatomic, retain) UIView *inputView, *inputAccessoryView;
- (void) setInputView:(UIView *)aView andToolbar:(UIToolbar *)aToolbar;
#end
EditableLabel.m
#implementation EditableLabel
#synthesize inputView, inputAccessoryView;
- (void) dealloc {
[inputView release];
[inputAccessoryView release];
[super dealloc];
}
- (void) setInputView:(UIView *)aView andToolbar:(UIToolbar *)aToolbar {
self.inputAccessoryView = aToolbar;
self.inputView = aView;
}
- (BOOL) canBecomeFirstResponder {
return YES;
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self becomeFirstResponder];
}
#end
EditableCell.h
typedef enum {
USERNAME, PASSWORD, MOBILE, BIRTHDAY, GENDER, DESCRIPTION, CATEGORY
} CellTag;
#interface EditableCell : UITableViewCell {
CellTag tag;
UIView *editPoint;
IBOutlet UILabel *headerLabel;
}
- (void) setTag:(CellTag)aTag andHeader:(NSString *)aHeader andEditPoint:(UIView *)aView;
#property (nonatomic) CellTag tag;
#property (nonatomic, retain) UIView *editPoint;
#property (nonatomic, retain) UILabel *headerLabel;
- (IBAction) editingDone:(id)sender;
- (void) showInputView;
- (void) hideInputView;
#end
EditableCell.m
#implementation EditableCell
#synthesize tag, editPoint, headerLabel;
- (void) dealloc {
[editPoint release];
[headerLabel release];
[super dealloc];
}
- (void) setTag:(CellTag)aTag andHeader:(NSString *)aHeader andEditPoint:(UIView *)aView {
self.tag = aTag;
self.headerLabel.text = aHeader;
self.editPoint = aView;
}
- (IBAction) editingDone:(id)sender {
[self hideInputView];
}
- (void) showInputView {
[self.editPoint becomeFirstResponder];
}
- (void) hideInputView {
[self.editPoint resignFirstResponder];
}
#end
EditableLabelCell.h
#interface EditableLabelCell : EditableCell {
IBOutlet UILabel *placeHolderLabel;
IBOutlet EditableLabel *editableLabel;
}
#property (nonatomic, retain) UILabel *placeHolderLabel;
#property (nonatomic, retain) EditableLabel *editableLabel;
- (void) setTag:(CellTag)aTag
andHeader:(NSString *)aHeader
andPlaceHolder:(NSString *)aPlaceHolder
andInputView:(UIView *)aView
andToolbar:(UIToolbar *)aToolbar;
- (void) setValue:(NSString *)aValue;
#end
EditableLabelCell.m
#implementation EditableLabelCell
#synthesize placeHolderLabel, editableLabel;
- (void) dealloc {
[placeHolderLabel release];
[editableLabel release];
[super dealloc];
}
- (void) setTag:(CellTag)aTag andHeader:(NSString *)aHeader andPlaceHolder:(NSString *)aPlaceHolder andInputView:(UIView *)aView andToolbar:(UIToolbar *)aToolbar {
[super setTag:aTag andHeader:aHeader andEditPoint:self.editableLabel];
self.placeHolderLabel.text = aPlaceHolder;
[self.editableLabel setInputView:aView andToolbar:aToolbar];
}
- (void) setValue:(NSString *)aValue {
if (aValue && aValue != #"") {
self.placeHolderLabel.hidden = YES;
self.editableLabel.text = aValue;
} else {
self.editableLabel.text = nil;
self.placeHolderLabel.hidden = NO;
}
}
#end
EditableGenderCell.h
#protocol EditableGenderCellDelegate <NSObject>
#required
- (NSString *) getTextForGender:(Gender)aGender;
- (void) genderChangedTo:(Gender)aGender forTag:(CellTag)aTag;
#end
#interface EditableGenderCell : EditableLabelCell <UITableViewDataSource, UITableViewDelegate> {
id<EditableGenderCellDelegate> delegate;
Gender gender;
IBOutlet UITableView *genderTable;
IBOutlet UIToolbar *doneBar;
}
- (void) setTag:(CellTag)aTag
andDelegate:(id<EditableGenderCellDelegate>)aDelegate
andHeader:(NSString *)aHeader
andGender:(Gender)aGender
andPlaceHolder:(NSString *)aPlaceHolder;
#property (nonatomic, retain) id<EditableGenderCellDelegate> delegate;
#property (nonatomic) Gender gender;
#property (nonatomic, retain) UITableView *genderTable;
#property (nonatomic, retain) UIToolbar *doneBar;
#end
EditableGenderCell.m
#implementation EditableGenderCell
#synthesize delegate, gender, genderTable, doneBar;
- (void) dealloc {
[delegate release];
[genderTable release];
[doneBar release];
[super dealloc];
}
- (void) setTag:(CellTag)aTag andDelegate:(id<EditableGenderCellDelegate>)aDelegate andHeader:(NSString *)aHeader andGender:(Gender)aGender andPlaceHolder:(NSString *)aPlaceHolder {
[super setTag:aTag andHeader:aHeader andPlaceHolder:aPlaceHolder andInputView:self.genderTable andToolbar:self.doneBar];
self.delegate = aDelegate;
self.gender = aGender;
[super setValue:[self.delegate getTextForGender:aGender]];
}
#pragma mark - Table view data source
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}
- (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];
}
switch (indexPath.row) {
case MALE:
switch (self.gender) {
case MALE:
cell.accessoryType = UITableViewCellAccessoryCheckmark;
break;
default:
cell.accessoryType = UITableViewCellAccessoryNone;
}
break;
case FEMALE:
switch (self.gender) {
case FEMALE:
cell.accessoryType = UITableViewCellAccessoryCheckmark;
break;
default:
cell.accessoryType = UITableViewCellAccessoryNone;
}
break;
}
cell.textLabel.text = [self.delegate getTextForGender:indexPath.row];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
#pragma mark - Table view delegate
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.gender = indexPath.row;
[super setValue:[self.delegate getTextForGender:self.gender]];
[self.delegate genderChangedTo:self.gender forTag:self.tag];
[tableView reloadData];
}
#end
Have a look at my answer to How to make a UITableViewCell with different subviews reusable?.
You should back up your custom tableviewcell nib files with a custom class representing your cell and encapsulate logic in it for example your gender picker. If you need to inform some outside controller of the gender you can make use of the delegate pattern.
Custom Gender picker in a TableViewCell
Ok let's start with the nib file, looking like this:
view hierarchy, don't set the File's Owner...
...set instead the class of the table view cell of your custom class:
The custom class
As you can see the class is almost empty, only providing the segmented control as property
GenderPickerTableViewCell.h
#interface GenderPickerTableViewCell : UITableViewCell
{
UISegmentedControl *genderPickerSegmentedControl;
}
#property (nonatomic, retain) IBOutlet UISegmentedControl *genderPickerSegmentedControl;
#end
GenderPickerTableViewCell.m
#import "GenderPickerTableViewCell.h"
#implementation GenderPickerTableViewCell
#synthesize genderPickerSegmentedControl;
#pragma mark -
#pragma mark memory management
- (void)dealloc
{
[genderPickerSegmentedControl release];
[super dealloc];
}
#pragma mark -
#pragma mark initialization
- (void)awakeFromNib
{
// initialization goes here, for example preselect a specific gender
}
#end
The table view using our new cell
I'll provide only the necessary methods to make this work. The TableViewCellFactory class is just a nib loader like I posted in my referenced answer above. The genderPickerTableViewCellWithTableView is just a convenience class method to return that special kind of cell without too much boilerplate code
The last important thing to note is the configuration of the cell, this is kept simple, I just access the segmented control directly and add a target to it which informs this view controller about a change.
#pragma mark -
#pragma mark view lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
tableView.rowHeight = 100.0;
tableView.dataSource = self;
tableView.delegate = self;
}
#pragma mark -
#pragma mark UITableView methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (UITableViewCell *) tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)anIndexPath
{
GenderPickerTableViewCell *cell = [TableViewCellFactory genderPickerTableViewCellWithTableView:aTableView];
[cell.genderPickerSegmentedControl addTarget:self
action:#selector(genderPicked:)
forControlEvents:UIControlEventValueChanged];
return cell;
}
#pragma mark -
#pragma mark UISegmentedControl action
- (void)genderPicked:(id)sender
{
UISegmentedControl *segmentedControl = (UISegmentedControl *)sender;
NSLog(#"selected index: %d", [segmentedControl selectedSegmentIndex]);
}
I hope this helps a bit for the beginning.
This is the code you can use for bouncing:
-(IBAction)textFieldDidBeginEditing:(UITextField *)textField { //Keyboard becomes visible
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3];
self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y - 50, self.view.frame.size.width, self.view.frame.size.height);
[UIView commitAnimations];
}
Just set y accordingly an call it when editing begins.