Re: Validation of fields in a navigation stack

2014-01-10 Thread Alex Zavatone
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 

Re: Validation of fields in a navigation stack

2014-01-09 Thread Luther Baker
Create your own UIBarButtonItem button ... set it on the navigation item's 
leftBarButton property. Do what you want when they tap it with your own handler.

The left bar button will cover the back button.

 On Jan 9, 2014, at 6:22 PM, Rick Mann rm...@latencyzero.com 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/lutherbaker%40gmail.com
 
 This email sent to lutherba...@gmail.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