NSTextField with built in validation - objective-c

I have in my app an NSTextField for creating a new file. I would like to have this textfield smart enough to show a small icon which show if the currently entered filename is valid (not yet exists) or not.
This icon should also change when the textfield contents change.
What is the way to achieve that?
Thanks!

This is the method you are looking for:
- (void)controlTextDidChange:(NSNotification *)aNotification
This is called by the textfield's delegate when the text changes. Perform your validation in the method and update your UI accordingly.

Related

Unable to disable Checkbox (NSButton) inside a disabled NSTableView

I have an app that contains an NSTableView instance with 2 columns. One column, is an instance of this:
#import <Cocoa/Cocoa.h>
#class NSTableView;
#interface MMCheckboxTableCellView : NSTableCellView
#property (weak) IBOutlet NSButton *checkboxField;
#end
and the implementation is all boilerplate with no custom code added at all. In code, the NSTableView instance sets tableview.enabled = YES (or NO) programmatically based on various state of the app. When tableview is disabled, the other column of the table, which is display only, stops responding to click actions, as expected. The checkbox column, above, continues to respond to clicks and lets the user check/uncheck the button instances.
To try to troubleshoot this, I added a Text Field (it's not hooked up to anything) in the the checkbox column and when the tableview is disabled, it isn't possible to enter text into the field. Is there something special about NSButton that I'm missing? Is it possible that because I derived this class from NSTableCellView with an added Check Box rather than using a Check Box Cell I'm running into this problem?
I finally figured this out. It appears that even though the NSButton is embedded in the NSTableView, setting enabled=NO on the table doesn't control the behavior of the button. The only thing that eventually made this work was to invoke setEnabled the the control based on the state of the app. This had to happen in the rendering of the cell, so when the state changes, it was also necessary to invoke NSTableView:reloadData so the visible cells would redraw immediately.
As an alternative, I decided to work around this same problem by setting up a computed property matching to my boolean property that returned either a blank or a checkmark character (✓). Then bound to this field as a normal NSTextfield for which the enabling/disabling works.
// Swift
// Computed variables on model for readonly display in table
var bIosText:String {return bIos ? "✓" : " " }
var bAndroidText:String {return bAndroid ? "✓" : " " }
Looks pretty good I think:
Of course this is only part of the solution, if you want to enable editing, you need to have multiple columns and hide/unhide as needed.
Do not embed an NSButton in the table view, only use a NSButtonCell. If your NSTableView was view based, it will switch to cell based (at least Xcode did that for me).
So this is wrong:
And this is right:
It should suffice to disable/enable the table view after this change, the button cell will behave accordingly.

How to handle first responder status for NSTextField subclass?

I'm working on a project which needs a special text field to edit byte values. My current solution is a dedicated readonly textfield and a "..." button to open a popover as shown in the image below:
Now I try to make my solution more user friendly. My goals are these:
If the text field gets the first responder status, the popover automatically opens.
The complete text is selected.
If the user leaves the text field with tab or selecting any field outside of the popover, the popover should automatically close.
If the user types any valid number and suffix the byte value is updated (e.g. "10 GB")
Currently I'm a little bit clueless. My questions are these:
Where is the best location to detect in in the subclass when the text field got first responder?
How can I detect when the field resigns being first responder?
Are there other, simpler solutions?
I could implement everything using - (BOOL)becomeFirstResponder as a hook to display the popover and observing the first responder to automatically hide the popover:
- (void)viewDidMoveToWindow
{
[super viewDidMoveToWindow];
[self.window addObserver:self forKeyPath:NSStringFromSelector(#selector(firstResponder)) options:0 context:NULL];
}
As a start point, I published a working project with the classes on GitHub (MIT License):
Project on GitHub

UITableView Cell - Edit?

Is it possible to use a UITableView to be able to enter a value into a database's field.
For example, if I was to have a UITableView pointing to a field within a database and if I wanted to enter a new entry into the database - tap on the UITableView Cell that would then allow keyboard input into the cell which ultimately end up being a new record in the database??
This is possible, but if something is possible doesn't mean you should be doing so.
You might ask why?
Well! you are trying to input data from view directly to database, this is a very bad practice. There are many reason for it being bad, the major is efficiency and security reasons.
You should consider using MVC pattern.
Now since its completely possible, I will explain the idea on how to do it and conclude with links that will have real code examples.
In tableView:cellForRowAtIndexPath:
add a TextField with tag (to get the reference back in future) and add it to contentView of the cell and have it hidden.
Now in tableView:didSelectRowAtIndexPath: make the cells editing property to YES.
Then, in tableView:willBeginEditingRowAtIndexPath:
get the reference to the textfield in contentview using viewWithTag: method and hide the textLabela and unhide the textfield.
In textfield's delegate textFieldDidEndEditing: make cell's editing property as no (yea, you need to keep the reference) unhide the textlabel and hide textfield.
In tableView:didEndEditingRowAtIndexPath: write methods which will commit the changes to your db.
Below are list of links which will get you code examples:
Having a UITextField in a UITableViewCell
Accessing UITextField in a custom UITableViewCell
iOS Database Tutorial
There are no examples for your requirement 'coz it bit bad way of doing things.
Yes its possible....
You can use delegate methods to take data form you cells textfield to your parent view controller and then save data in database.

UITextField - Action on resignFirstResponder -- possible?

I have created a form that has a number of text fields that save to NSStrings that are then used deeper in the app.
Currently, if you hit the return key (done) on the GUI keyboard, the keyboard is dismissed, and the data in the text field is saved to its NSString. Likewise, if the background is touched the same occurs.
However, if I touch another text field, without doing one of the above first, the variable is not saved. Is there a way to do this? Perhaps a way to perform an action when a specific text field release firstresponder?
The best solution for your issue is just to use the
-(void)textFieldDidEndEditing:(UITextField *)textField
And then you can just access the textField and store the textFields text in the appropriate string every time focus is lost.

NSTextField setEnabled

I have a NSTextField object in my window which has to be disabled when a check box is clicked.
I have written a IBAction to receive the check box click and disabled/enabled the text filed based on the check box state.
[mName setEnabled: [mNameCheck state]];
This work fine with the basic functionality, but I found some strange behavior.
You update some detail in the text filed and click on check box the text filed get disabled old content.
Example:
Stage 1: Text filed has the content
"Name"
Stage 2: Update the text filed
content as "Girish"
Stage 3: Click check box (to disable
the text filed)
Stage 4: Text filed disable with the
content as "Name"
The issue get resolved if I resign the responder and set responder to some other controller before the text field is disabled.
In my case I can not assign the responder to check box(it does not take) or any other controller so I did some thing like bellow which works fine
[mName resignFirstResponder];
[mName becomeFirstResponder];
resign and assign responder with same controller.
I am just wondering is this solution is correct or any better solution to this issue?
As the docs state, do NOT call -resignFirstResponder or -becomeFirstResponder directly. Call -[NSWindow makeFirstResponder:] instead. It is acceptable to pass in nil and status will pass to the window itself.
You could try calling -[NSWindow selectNextKeyView:] although I'm not entirely certain what will happen if it doesn't find a valid next key view. Try it and see. If that doesn't work you'll have to fallback to calling -nextValidKeyView and -makeFirstResponder yourself.
If you set the text field to be Continuous in Interface Builder, the value of the field will be set as soon as a change is made in the field rather than when it loses focus. You can programmatically set this value with [yourTextField setContinuous:YES].