I want to have a window that needs to accept some user input, for this I have the following:
NSWindowloaded from nib withNSWindowController, which is also its delegate- Couple of
NSTextField's withNSNumberFormatter - Using bindings, the
NSTextField's are bound to a integer properties in theNSWindowController(I didn't usedNSObjectControllerfor simplicity but can add it if needed) - A 'done'
NSButtonwhich the user clicks when finished to accept the changes and close the window - In controller's
windowShouldClose:method do a final validation and decide whether I can close the window
What I want to achieve is pretty simple, yet Cocoa insists on making this challenging:
NSTextFieldshould accept only a number for it final value, which is also greater than zero- If the user tries to insert non numeric values or zero, there should be an alert prompting the user to fix his entry
- When the user clicks on done:
- Do other custom validation (e.g. compare if one number is great than the other)
- If the values are correct, accept the changes and close the window (the 'model' should be already updated with the values via bindings)
- If the values are incorrect, the user should be prompted with a choice whether to fix the entry (leaving the window open) or close the window and discard changes
Simple enough. The NSNumberFormatter should already cover most of the task and together with the bindings, this should be pretty easy to achieve.
Problem #1:
I couldn't find a way to change the error message that is displayed to the user in the alert when NSTextField loses focus and the value is incorrect to something more descriptive. Is there any way to do this? Or I need to implement my own NSFormatter somehow?
Problem #2:
When user changes a value in the NSTextField and clicks on the 'done' button, Cocoa doesn't consider this as a trigger to update the value of the model NSTextField is bound to. This may be the standard OSX behavior but is something that doesn't make any sense.
I was able to work around this by calling [window makeFirstResponder:nil] in the action of the 'done' button to force the NSTextField lose focus and update the value but I wonder if this is the right way to achieve this.
Problem #3:
And here is where I really scratch my head. If the user enters an incorrect value (like non integers) in the NSTextField and click 'done' button, the validation doesn't kick in and the NSTextField will continue to have the incorrect values while the model is not updated.
I'd expect that the "invalid" alert will still be displayed and I have some place to insert code to make a decision whether to close the window or not but I couldn't find any way to override this behavior.
What should be the standard practices to achieve these requirements? Should I abandon the formatter and/or bindings and just do it all manually using actions?