Cannot Reload Tableview from custom cell - iphone

I have a UITableView with custom tableview cells. One of my Cell has a UITextField, I'm handling the textfield delegate methods in the custom tableviewCell class. I need to reload the tableview once the user entered a text, I had done the below thing but not worked , Any idea please help me.
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
UITableView *parentTable = (UITableView *)self.superview;
[parentTable reloadData];
}

Register the view controller to receive notifications that the data has been changed, and have it refresh the table when it receives one. Then have the parser send it out.
Registering for it is easy:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reloadTableView:)
name:#"reloadTableView"
object:nil];
Your refresh method needs to be set up to receive these notifications, along these lines:
- (void)reloadTableView:(NSNotification *)notif {
[self.yourTableName reloadData];
}
And it's important to stop observing in your ViewDidUnload:
[[NSNotificationCenter defaultCenter] removeObserver:self];
Then in the parser you need to simply add this when it's complete:
[[NSNotificationCenter defaultCenter] postNotificationName:#"reloadTableView"
object:nil];
The view controller (and anyone else observing the notification with that name) will get the message and perform its task.
Thanks..

CustomCell.h
#property (nonatomic, copy) void(^tapHandler)(NSUInteger tag);
CustomCell.m
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
NSUInteger tag = 10; //Need to change the tag
self.tapHandler(10);
}
Controller.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
// Whatever content was previously there. Add the below line in addition
cell.tapHandler = ^(NSUInteger tag){
[tableView reloadData];
};
return cell
}
Hope it helps!

first , the superview of the textfiled is not UITableview, it is tableviewcell or tableviewcell.contentview (depends on your code)
then, you just need to set the tableview as your view controller's member ,or property,
then
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[self.tableview reloadData];
}

Try this,
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[self.parentTable reloadData];
}

It's better to keep a reference of table view in CustomCell
// interface
UITableView *tableView;
// propery
#property (nonatomic)UITableView * tableView;
Then
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//your stuff
cell.tableView= tableView;
}

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
UITableView *parentTable = (UITableView *)textField.superview.superview;
[parentTable reloadData];
}

Don't reload whole table view for that small operation. Just reload the Cell in which the text field is. Also didnot forget to update your data source as table view cell fetch the data from the data source while the cell is loading.
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[tableViewDataSource addObject:textField.text];//this will fill the data source with data of textfield
CustomCell *cell = (CustomCell *)textField.superview.superview;
NSIndexPath *indexPath = [parentTable indexPathForCell:cell];
[parentTable reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}

By (UITableView *)self.superview; you will not get the table view. Try below code :
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
YourCell *cell = (YourCell *)[[textField superview] superview]; // you will get cell
UITableView *table = cell.superview; // you will get table view
[table reloadData];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
tableReload++;
NSString *CellIdentifier = [NSString stringWithFormat:#"cell %d%d",indexPath.row,tableReload];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
cell.textLabel.text = #"Hello";
}
// Configure the cell.
return cell;
}

Try this,
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[self.yourTableName reloadData];
[self.yourTableName reloadInputViews];
}

Related

How do I retrieve UITableView row number of a UISwitch?

I have tried several approaches posted here, but I cannot get my table full of switches to return an index value for the cell of the changed switch. I am creating the view containing the table programmatically (no xib).
TableSandboxAppDelegate.m I instantiate the view controller in didFinishLaunchingWithOptions: with:
...
TableSandboxViewController *sandboxViewController = [[TableSandboxViewController alloc]
init];
[[self window] setRootViewController:sandboxViewController];
...
TableViewController.h file reads:
#interface TableSandboxViewController : UITableViewController
{
NSMutableArray *_questionOrder;
NSMutableArray *switchStates;
}
#end
TableViewController.m cellForRowAtIndexPath: reads:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
UISwitch *theSwitch = nil;
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"MainCell"];
theSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
theSwitch.tag = 100;
[theSwitch addTarget:self action:#selector(switchChanged:)
forControlEvents:UIControlEventValueChanged];
[cell.contentView addSubview:theSwitch];
} else {
theSwitch = [cell.contentView viewWithTag:100];
}
if ([[switchStates objectAtIndex:indexPath.row] isEqualToString:#"ON"]) {
theSwitch.on = YES;
} else {
theSwitch.on = NO;
}
return cell;
TableViewController.m -(IBAction)switchChanged:(UISwitch *)sender reads:
UITableViewCell *theParentCell = [[sender superview] superview];
NSIndexPath *indexPathOfSwitch = [self.tableView indexPathForCell:theParentCell];
NSLog(#"Switch changed at index: %d", indexPathOfSwitch.row);
My log result is always "Switch changed at index: 0". I feel like the problem is in that CGPoint line where I've tried combinations of replacements for "sender" ([sender superview], [[sender superview]superview], etc). I don't feel like that line is pointing to the view that displays the table.
What am I doing wrong?
Note added 10/9, 9:15 EDT: my goal is to be able to handle about 100 yes/no questions in the table, so reuse is a key. I want to scroll and have the table the state of each switch, as well as be able to retrieve them when leaving the view.
Tags is an okay solution, but a little clumsy because the cells - and therefore their subviews - are continually being reused, changing their rows - and therefore the tags they need.
Instead, I generally keep one of these around:
- (NSIndexPath *)indexPathWithSubview:(UIView *)subview {
while (![subview isKindOfClass:[UITableViewCell self]] && subview) {
subview = subview.superview;
}
return [self.tableView indexPathForCell:(UITableViewCell *)subview];
}
Then when I get an IBAction:
- (IBAction)someSubviewAction:(id)sender {
NSIndexPath *indexPath = [self indexPathWithSubview:(UIView *)sender];
// carry on from here
}
You may set switch view tag to row index. Instead of theSwitch.tag = 100;
do
-(UITableViewCell*)tableView:table cellForRowAtIndexPath:indexPth
{
UISwitch *theSwitch = nil;
if (cell == nil) {
...
// as per your example
[cell.contentView addSubview:theSwitch];
} else {
theSwitch = subviewWithClass(cell.contentView, [UISwitch class]);
}
theSwitch.tag = indexPath.row;
...
}
Add this helper function to replace viewWithTag: call
UIView *subviewWithClass(UIView *contentview, Class klass)
{
for (UIView *view in contentview.subviews)
if ([view isKindOfClass:klass])
return view;
return nil;
}
Then retrieve tag, that is a row index now, in your switchChanged function
-(IBAction)switchChanged:(UISwitch *)sender {
NSLog(#"Selected Switch - %d", sender.tag);
...
}
If you use something block-based (like https://github.com/brightsoftdev/iOS-Block-Based-Bindings/blob/master/UISwitch%2BBindings.m), you don't need to worry about getting the row, because you can reference the indexPath that is passed into tableView:cellForRowAtIndexPath: in your block.
Similar to #danh, I've come up with this solution using an extention which I've used multiple times.
#interface UIView (Find)
- (id)findSuperviewOfClass:(Class)class;
- (NSIndexPath *)findIndexPath;
#end
#implementation UIView (Find)
- (id)findSuperviewOfClass:(Class)class
{
return [self isKindOfClass:class] ? self : [self.superview findSuperviewOfClass:class];
}
- (NSIndexPath *)findIndexPath
{
UITableView *tableView = [self findSuperviewOfClass:[UITableView class]];
return [tableView indexPathForCell:[self findSuperviewOfClass:[UITableViewCell class]]];
}
#end
for iOS6+ you could maintain a NSMutableArray queuedSwitches
in -tableView:cellForrowAtIndexPath: you would take a switch, if not empty and places it on the custom cell and assign it to a property. If empty you create a new one.
in -tableView:didEndDisplayingCell:forRowAtIndexPath: you would add it to quededSwitches and remove it from it cell.
This will just allocate enough switches for visible cells and reuse them.
the switches are all wired up to one action.
-(void)switchAction:(UISwitch *)switch
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:[switch superView]];
//…
}
You could create a subclass of UISwitch and add an indexPath property, then just set the indexPath in cellForRowAtIndexPath:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
SwitchCell *returnCell = [tableView dequeueReusableCellWithIdentifier:#"SwitchCell" forIndexPath:indexPath];
returnCell.switch.indexPath = indexPath;
return returnCell;
}

expanding cell to show a nib file view

I want to expand the cell when selected to show a row of buttons like the image above. I have a xib file which shows a cell that is 320 wide x 140 tall. I have subclassed that UITableViewCell. Additionally I have another xib file that has the row of buttons as shown in blue ink in the image above.
I am able to load the row of buttons using initWithCoder using this answer from a really smart guy!
However, it overwrites all my other views inside the MyCustomCell.
How can I load the xib just when the cell expands so that it is positioned in the lower half of the 140pt tall cell?
After doing a little more research, I found a different way to do something like what you want using just one cell. In this method, you have just the taller cell, but return a height that only lets you see the top half of the cell unless its selected. You have to do two things in the design of your cell to make this work. First select the box for "clip subviews" in IB, so the buttons won't show outside their view (the cell). Second, make the constraints such that the buttons are all lined up vertically with each other and give one of them a vertical spacing constraint to one of the UI elements in the top of the cell. Make sure none of the buttons has a constraint to the bottom of the cell. By doing this, the buttons will maintain a fixed distance with the top elements (which should have a fixed space to the top of the cell), which will cause them to be hidden when the cell is short. To animate the change in height, all you have to do is call beginUpdates followed by endUpdates on the table view.
#import "TableController.h"
#import "TallCell.h"
#interface TableController ()
#property (strong,nonatomic) NSArray *theData;
#property (strong,nonatomic) NSIndexPath *selectedPath;
#end
#implementation TableController
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"TallCell" bundle:nil] forCellReuseIdentifier:#"TallCell"];
self.theData = #[#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight",#"Nine"];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.theData.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath isEqual:self.selectedPath]) {
return 88;
}else{
return 44;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TallCell *cell = [tableView dequeueReusableCellWithIdentifier:#"TallCell" forIndexPath:indexPath];
cell.label.text = self.theData[indexPath.row];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([self.selectedPath isEqual:indexPath]) {
self.selectedPath = nil;
}else{
self.selectedPath = indexPath;
}
[tableView beginUpdates];
[tableView endUpdates];
}
This, I think gives you the desired animation when you pick the first cell, but you get a somewhat different animation if you then pick a cell below the currently selected one. I don't know of any way around that.
I'm not sure what you have in your two xib files, but the way I would do it is to have one xib file for the shorter cell, and one for the taller cell (that has everything in it that you show in your drawing). I did it like this, with two xib files like I mention above:
#import "TableController.h"
#import "ShortCell.h"
#import "TallCell.h"
#interface TableController ()
#property (strong,nonatomic) NSArray *theData;
#property (strong,nonatomic) NSIndexPath *selectedPath;
#end
#implementation TableController
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"ShortCell" bundle:nil] forCellReuseIdentifier:#"ShortCell"];
[self.tableView registerNib:[UINib nibWithNibName:#"TallCell" bundle:nil] forCellReuseIdentifier:#"TallCell"];
self.theData = #[#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight",#"Nine"];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.theData.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath isEqual:self.selectedPath]) {
return 88;
}else{
return 44;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (! [self.selectedPath isEqual:indexPath]) {
NSLog(#"returning short");
ShortCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ShortCell" forIndexPath:indexPath];
cell.label.text = self.theData[indexPath.row];
return cell;
}else{
NSLog(#"returning long");
TallCell *cell = [tableView dequeueReusableCellWithIdentifier:#"TallCell" forIndexPath:indexPath];
cell.label.text = self.theData[indexPath.row];
return cell;
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if ([self.selectedPath isEqual:indexPath]) {
self.selectedPath = nil;
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
return;
}
NSIndexPath *lastSelectedPath = self.selectedPath;
self.selectedPath = indexPath;
if (lastSelectedPath != nil) {
[self.tableView reloadRowsAtIndexPaths:#[indexPath,lastSelectedPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}else{
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}

uitableview reloadRowsAtIndexPaths not working

I have a tableviewcell in the RegisterViewController, when i click on it, it push to the SelectCityViewController where i can pick a city from a uipickerview. and I have defined a delegate in the SelectCityViewController. But when i implement the delegate method, i got the city back from the pickerview and the selected indexpath from didSelectRowAtIndexPath in RegisterViewController. When i check the log, i get the city, and the selected indexpath. but when i call reloadRowsAtIndexPaths, the cell still got the old titlelabel text. the code:
SelectCityViewController.h
#protocol SelectCityDelegate <NSObject>
- (void)didGetCity:(City *)city;
#end
SelectCityViewController.m
- (void)finished:(UIBarButtonItem *)buttonItem
{
if ([self.delegate respondsToSelector:#selector(didGetCity:)]) {
[self.delegate didGetCity:self.city];
}
NSLog(#"%#", self.city.city);
[self.navigationController popViewControllerAnimated:YES];
}
RegisterViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 2) {
self.selectedIndexPath = indexPath;
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
SelectCityViewController *signUp = [storyBoard instantiateViewControllerWithIdentifier:#"SignVC"];
signUp.delegate = self;
[self.navigationController pushViewController:signUp animated:YES];
}
}
- (void)didGetCity:(City *)city
{
NSLog(#"%#", city.city);
NSLog(#"%#", selectedIndexPath);
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:selectedIndexPath];
cell.textLabel.text = city.city;
[self.tableView reloadRowsAtIndexPaths:#[selectedIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}
I think the problem is in the below code you don't have to set the value here, because when you will reload, it will override the value with what is in the function where you are creating your cells.
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:selectedIndexPath];
cell.textLabel.text = city.city;
Just reload the cell, and put above code in your
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//Cell intialization and other things
cell.textLabel.text = city.city;
}
didGetCity needs to update the model that backs the table, not the table cell itself. How do you answer numberOfRowsInSection:? With the count of some array?
That array at index selectedIndexPath.row needs to change. cellForRowAtIndexPath: should initialize the cell with that same data. Then your didGetCity method updates the array and reloads. It should not refer to cells.

uitableView reloadData doesn't work after setting delegate, datasource and file's owner connection

I have googled and done lot of research from my side to find out why the reloadData method on tableview wouldn't work. I checked all the possible solutions like the datasource is set, delegate is set, the tableview is connected to the file's owner.
After all these, when I am trying to reload the tableview, the no. of rows method gets called, but the cell for rowAtIndexPath doesn't get called. Below is the code that I have written. Please let me know, where I am going wrong
- (void)onReservationListSuccess:(NSArray *)rData
{
if ( rData != nil )
{
resList = [[NSArray alloc] initWithArray:rData];
if([resList count] > 0)
{
[self.tripsTableView reloadData];
//[self.tripsTableView beginUpdates];
//[self.tripsTableView reloadSections:[NSIndexSet indexSetWithIndex:0]
// withRowAnimation:UITableViewRowAnimationNone];
//[self.tripsTableView endUpdates];
}
else
{
[tripsTableView reloadData];
[tripsTableView setHidden:YES];
[noTripsLabel setHidden:NO];
}
}
if(fsnNeedsRefresh == YES)
{
[[NSNotificationCenter defaultCenter] postNotificationName:UpdateFSNList object:nil];
fsnNeedsRefresh = NO;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int temp=[resList count];
NSLog(#"The no. of rows are %d", temp);
NSLog(#"Testing Purpose");
NSLog(#"The pnr details of the object is:%#",((TripData *)[resList objectAtIndex:0]).pnrDescription);
return 1;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"The cell for the row at indexpath is getting called");
static NSString *CellIdentifier = #"TripCellIdentifier";
TripCell *cell = (TripCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TripCell" owner:self options:nil];
for(id oneObject in nib)
if([oneObject isKindOfClass:[TripCell class]])
cell = (TripCell *)oneObject;
}
// Set up the cell...
TripData *tripData = (TripData *)[resList objectAtIndex:indexPath.row];
cell.pnrLabel.text = tripData.pnr;
NSLog(#"The cell text is %#",tripData.pnr);
cell.pnrDescriptionLabel.text = tripData.pnrDescription;
NSLog(#"The cell text is %#",tripData.pnrDescription);
cell.pnrTypeLabel.text = tripData.pnrType;
NSLog(#"The cell text is %#",tripData.pnrType);
if(checkInAllowed)
{
cell.checkInButton.tag = indexPath.row;
[cell.checkInButton addTarget:self action:#selector(checkIn:) forControlEvents:UIControlEventTouchUpInside];
}
else
{
[cell.checkInButton setEnabled:NO];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller
TripData *tripData = (TripData *)[resList objectAtIndex:indexPath.row];
NSLog(#"%#", tripData.pnr);
if(tripData != nil)
{
TripOverviewViewController *tripOverviewViewController = [[TripOverviewViewController alloc] initWithTrip:tripData];
[self.navigationController pushViewController:tripOverviewViewController animated:YES];
[tripOverviewViewController release];
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
From this part of code I cannot say exactly why it does not work but I'll try to explain how reloadData works.
First, how UITableView works: basically, it's a scrollview. When it is drawn, it checks how many rows it has, then checks their height and from its size and scroll position it decides which rows are currently displayed. Then it asks the delegate to return a UITableViewCell for every displayed row.
When the table is scrolled, it removes the hidden cells from the view hierarchy and adds the cells that have appeared.
And now the tricky part - what does reloadData do? It just removes all the UITableViewCells from the table hierarchy. Nothing more. The actual update is done when the table is drawn for the first time after reloadData.
So, my suggestion is - check that your table is not hidden and check its frame. Also, I see that you are accessing both a property getter self.tripsTableView and an ivar tripsTableView. This is confusing. Do they both return the same?

Accessing UITextField in a custom UITableViewCell

I have a UITableViewCell (with associated UITableViewCell sub class, .m & .h) created in IB which contains a UITextField. This UITextField is connected up to an IBOutlet in the UITableViewCell sub class and also has a property. In my table view controller I am using this custom cell with the following code:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"textfieldTableCell"];
if (cell == nil) {
// Create a temporary UIViewController to instantiate the custom cell.
UIViewController *temporaryController = [[UIViewController alloc] initWithNibName:#"TextfieldTableCell" bundle:nil];
// Grab a pointer to the custom cell.
cell = (TextfieldTableCell *)temporaryController.view;
// Release the temporary UIViewController.
[temporaryController release];
}
return cell;
}
The UITextField displays fine and the keyboard pops up when clicked as expected, but how do I access (get .text property) the UITextField that each row contains? and also how do I handle the 'textFieldShouldReturn' method of the UITextFields?
I think what the OP is trying to understand is how to access the UITextField value once the user has entered data into each fields. This will not be available at the time the cells are created as suggested by #willcodejavaforfood.
I've been implementing a form and trying to make it as user friendly as possible. It is doable but be aware that it can get quite convoluted depending on the number of UITableViewCells / UITextFields you have.
Firstly to your question re: accessing the values of UITextField:
1) Make your view controller a <UITextFieldDelegate>
2) Implement the following method:
- (void) textFieldDidEndEditing:(UITextField *)textField {
NSIndexPath *indexPath = [self.tableView indexPathForCell:(CustomCell*)[[textField superview] superview]]; // this should return you your current indexPath
// From here on you can (switch) your indexPath.section or indexPath.row
// as appropriate to get the textValue and assign it to a variable, for instance:
if (indexPath.section == kMandatorySection) {
if (indexPath.row == kEmailField) self.emailFieldValue = textField.text;
if (indexPath.row == kPasswordField) self.passwordFieldValue = textField.text;
if (indexPath.row == kPasswordConfirmField) self.passwordConfirmFieldValue = textField.text;
}
else if (indexPath.section == kOptionalSection) {
if (indexPath.row == kFirstNameField) self.firstNameFieldValue = textField.text;
if (indexPath.row == kLastNameField) self.lastNameFieldValue = textField.text;
if (indexPath.row == kPostcodeField) self.postcodeFieldValue = textField.text;
}
}
I also use a similar syntax to make sure the current edited field is visible:
- (void) textFieldDidBeginEditing:(UITextField *)textField {
CustomCell *cell = (CustomCell*) [[textField superview] superview];
[self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
And finally, you can handle textViewShouldReturn: in a similar way:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSIndexPath *indexPath = [self.tableView indexPathForCell:(CustomCell*)[[textField superview] superview]];
switch (indexPath.section) {
case kMandatorySection:
{
// I am testing to see if this is NOT the last field of my first section
// If not, find the next UITextField and make it firstResponder if the user
// presses ENTER on the keyboard
if (indexPath.row < kPasswordConfirmField) {
NSIndexPath *sibling = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section];
CustomCell *cell = (CustomCell*)[self.tableView cellForRowAtIndexPath:sibling];
[cell.cellTextField becomeFirstResponder];
} else {
// In case this is my last section row, when the user presses ENTER,
// I move the focus to the first row in next section
NSIndexPath *sibling = [NSIndexPath indexPathForRow:kFirstNameField inSection:kOptionalSection];
MemberLoginCell *cell = (MemberLoginCell*)[self.memberTableView cellForRowAtIndexPath:sibling];
[cell.cellTextField becomeFirstResponder];
}
break;
}
...
}
In cellForRowAtIndexPath: include this code,
yourTextField.tag=indexPath.row+1; //(tag must be a non zero number)
Then access the textField using
UITextField *tf=(UITextField *)[yourView viewWithTag:tag];
There is even more simpler way to solve both problems,
1.Create a custom uitableviewCell class for the cell, (e.g.textfieldcell)
2.Now, in the textfieldcell.h file call textFieldDelegate
3.In the textfieldcell.m file write textFieldDelegate methods
ie
-(BOOL)textFieldShouldReturn:(UITextField *)textField;
-(void)textFieldDidEndEditing:(UITextField *)textField;
(first problem)Now, in
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[self.mytextBox resignFirstResponder];
return YES;
}
5.(second problem),
-(void)textFieldDidEndEditing:(UITextField *)textField
{
nameTextField = mytextBox.text;
}
6.create a custom delegate method in the MaintableViewController
#protocol textFieldDelegate <NSObject>
-(void)textName:(NSString *)name;
#end
7.In MaintableViewController.m file write the implementation of the delegate method,
-(void)textName:(NSString *)name{
Nametext = name;
NSLog(#"name = %#",name);
}
8.call the delegate method in the cell class , and pass the variable in the didendmethod
9.now, assign self to cell.delegate ,when initializing the cell in uitableview
10.thats it you got the variable passed from textfield to the main view, Now do whatever u want with the variable
This is how I managed to get the text inside the UITextField inside my custom UITableViewCell in Swift. I accessed this inside my UIButton inside another custom UITableViewCell that has an #IBAction on my UITableViewController. I only have one section in my UITableViewController but that doesn't matter anyway because you can easily set and assign this yourself.
#IBAction func submitButtonTapped(sender: UIButton) {
print("Submit button tapped")
let usernameCell = self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0)) as! UsernameTableViewCell
print("Username: \(usernameCell.usernameTextField.text)")
}
Whenever I tapped my UIButton, it gives me the updated value of the text inside my UITextField.
If you have created a class for your custom cell I'd advise you to work against it.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCustomCell* cell = (MyCustomCell *) [tableView dequeueReusableCellWithIdentifier:#"BDCustomCell"];
if (cell == nil) {
// Load the top-level objects from the custom cell XIB.
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"MyCustomCell" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = (MyCustomCell *) [topLevelObjects objectAtIndex:0];
}
// This is where you can access the properties of your custom class
cell.myCustomLabel.text = #"customText";
return cell;
}
This tutorial was helpful to me. You can reference whatever object you need through the tag.
In the Storyboard drag on a UIImageView or UITextField etc. and set the tag to 100 (whatever you want) then in your - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath use the tag to reference it.
Here's something you could do, just remember to set the tags in the storyboard:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UITextField *tField = (UITextField *)[cell viewWithTag:100];
return cell;
}