I've had to deal with something that sounds similar in a UITableView earlier 
this week.  

FYI, completing an edit by dismissing the keyboard commits the changed data to 
the datasource.
Simply tapping a field in a cell invokes editing.

Now, I'm not sure if this is "the best" way, or the standard way, but it is a 
way and it works.

Care needs to be taken as (from what I have seen in iOS 7), certain events are 
not sent to the desired objects (UITextField delegates) that you would expect 
to be sent, while others are.  Notably, these are the events of a text field 
starting being edited, a text field ending being edited and a change within a 
text field.

As these edits on iOS will be handled through display of a keyboard, and 
possibly the clicking of the clear button, we need to make sure that the events 
for keyboard display and dismissal are also caught.

According to the research that I have done, if you make a UITableView that is 
not fullscreen or is in a UIView and extended by use of UITableView and 
UITextField delegates, you will have to register to receive notifications for 
all events that are not automatically sent to your view controller.

Like you, all I am checking for right now is "this text field is not empty", 
but once this condition is in place, it can be changed to be a rule set if you 
wish to handle other conditions.

All data that is displayed is linked from a singleton and committed back to it 
on the dismissal of the keyboard.  A reloadData is then sent to the tableView, 
but really should just be sent to the cell.

One other thing is that I wasn't able to easily determine the current field 
being edited when receiving the textFieldDidChangeEditing message (if anyone 
knows, I'm all ears).  This meant adding a property to the VC called 
fieldBeingEdited and when the field starts being edited, store a reference to 
that field and clear it when editing stops.  Actually, since we will be 
constantly setting it when editing starts, you could never clear it, but that 
just seems sloppy.

To make sure the notifications are caught, I created two methods, 
configureForKeyboardDisplayNotifications and configureForTextEditNotifications.

In all the event methods that I care about, I call the updateUIOnEdit to 
conditionally format the UITextField's appearance (reddish if invalid, green 
border if legit).

These are:
-(void)textFieldDidBeginEditing:(UITextField *)textField;
-(void)textFieldDidEndEditing:(UITextField *)textField;

-(void)textFieldDidChangeEditing; // My custom method that is called as a 
result of subscribing to the UITextFieldTextDidChangeNotification

Don't add notifications for the UITextFieldDidBeginEditingNotification and 
UITextFieldDidEndEditingNotification, as these are already sent to the 
delegate, but for some reason, UITextFieldTextDidChangeNotification is not.

Notice that there is no textfield passed to textFieldDidChangeEditing.  I'm not 
sure how to get the textField reference from the notification, so this is where 
I use the fieldBeingEdited reference to the currently edited textField.

In my cell subclass, I have the formatting code, so the viewController's 
updateUIOnEdit calls the cell's formatViewConditionally method.
Upon return to the viewController's class I can issue a reload data just for 
that cell.

A nice article to get you started which has a great method for getting a 
textField's parent cell is this one: 
http://objcsharp.wordpress.com/2013/09/09/editable-uiTableviewcontroller/

Since I'm doing this for a tableView that is not full screen, there will be 
issues when the keyboard appears over the bottom cells in the table and the 
cells will be obscured by the keyboard.  If you haven't tested for this, I'd 
certainly check that case.  According to Apple docs, the process is to raise 
the contentInset for the bottom of the table view and then scrolling the 
tableView to the new position using an 
atScrollPosition:UITableViewScrollPositionMiddle.  In my experience with a 
tableView that is not touching the top and bottom of the screen, this fails to 
scroll to the desired position using 
atScrollPosition:UITableViewScrollPositionMiddle or 
atScrollPosition:UITableViewScrollPositionTop and I have had to simply find a 
number that works and use that.   Just an FYI.

Not sure how this would help in a UINavigationController, but this is what I 
have working in an editable UITableView.

How about disabling the back button if the UITextFieldDelegate returns no?  Or 
simply setting enabled state of the back button to observe what the 
UITextFieldDelegate returns?

Cheers.

On Jan 9, 2014, at 7:22 PM, Rick Mann wrote:

> What's the right way to validate fields in an editable detail view in a 
> navigation stack? It seems that the API doesn't really provide a good means 
> to do so without a lot of contortions, and so I wonder what the intended 
> behavior is.
> 
> Here's what I've got: A UINavigationController stack with a UITableView that 
> shows a list of Jobs. You can add a new job, or select an existing job, and 
> it pushes a new UITableViewController that is a detail view of the Job. Some 
> of the fields in this detail view are editable (i.e. "Name").
> 
> I don't want to allow the user to specify an empty name. So I had a separate 
> "Save" button in the top-right of the nav bar, and I would validate 
> everything in there before actually saving the changes to Core Data. I also 
> had to subclass UINavigationController to prompt the user to discard changes 
> if they tapped the back button (I also had to do this if they did something 
> else to dismiss the UIPopover all this lives in).
> 
> For other reasons, I'd like to change this behavior a bit to avoid the save 
> step all together, and to always save any change. But I still need to 
> validate that they don't try to save an empty name. I'm trying to do this 
> with -[UITextFieldDelegate textFieldShouldEndEditing:], in which I present an 
> alert and return NO if the field is empty. But that doesn't work if they tap 
> the "back" button. In this case, I'm content with simply undoing whatever 
> change they made and not saving the changes without prompting, but I have to 
> be able to detect that that's what's happening. There is no 
> UINavigationControllerDelegate method for popping a view controller, only 
> showing a new one.
> 
> I guess I could set a flag in -viewWillDisappear: indicating that the field 
> is ending editing because the view is going away, and save or discard 
> (without an alert) in that case.
> 
> What are your thoughts?
> 
> -- 
> Rick
> 
> 
> 
> _______________________________________________
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/cocoa-dev/zav%40mac.com
> 
> This email sent to z...@mac.com


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to