Getting the length of an NSTextField's text property - objective-c

I am having a problem finding the length of a text field's text!
I searched here a lot and just found that it would work with textfield.text.length or something like that.
My problem is textfield.text is not working for me!
If I write this code: textfield.text; then I get an error like this:
property "text" not found on object of type NSTextField
I have to find the length of an text field in order to limit the number of characters.
What should I do? Thanks in advance.

Most of the classes in AppKit, as opposed to UIKit, don't have properties. NSTextField doesn't even have a method called text. You need the stringValue method, which is inherited from NSControl

The generally accepted way of doing this (limiting the length of NSTextField) is by using the NSFormatter helper class. See Here

To limit the length you add the delegate methods to your controller by adding
< UITextFieldDelegate >
in the header file. Then in the implementation add the following method:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
In here just check the length and either return the string or just the string length you want.
You can get the length with:
[[textfield stringValue] length]
In interface builder be sure and add the file owner as the delegate to the text field

Related

NSTextField Autocomplete / Suggestions

Since some days I am trying to code an autocompletion for a NSTextField. The autocompletion should look that way, that when the user clicks on the NSTextfield a list should be displayed under the TextField which possibilities are available. After typing one letter or number the list should refresh with the possibilities.
The suggestions in this list should come from an NSMutableArrayor a NSMutableDictionary
This autocomplete / autosuggestion method should be for a MAC application.
Just adding to #AbcdEfg's answer, to make NSComboBox case-insensitive, you can subclass it and override it's [completedString:] method like this:
- (NSString *) completedString:(NSString *)string {
NSUInteger l = [string length];
if (!!l)
for (NSString *match in [self objectValues])
if ([[match commonPrefixWithString:string options:NSCaseInsensitiveSearch] length] == l)
return [match stringByReplacingCharactersInRange:NSMakeRange(0, l) withString:string];
return nil;
}
You can use NSComboBox for that matter. You also need to set its Autocompletes attribute in IB or [comboBox setCompletes:YES] in code.
Keep in mind that it is case-sensitive.
However if you need it to be done in the exact way that you described, you need to make the list by subclassing NSWindowController and NSTableView and change them to look like a list or menu to show under you NSTextField. Set the NSTextField's delegate and do the search and list update on text changes.
Avoid the NSMenu in this case as it will take away the focus from the text field while you are typing.
Apple addressed it in WWDC 2010 Session 145.
They explained about a text field with suggestions menu and how to get it to work. They also provide the sample codes in their website.
You can find the sample code here.

NSString with fixed length

I want an nsstring object that can only store specified lenght of character in it.
If it exceeds it should get truncated from left. For example if i set lenght to 5, and I enter value as Ileana then it should store leana.
I tried by making a category on nsstring but i am out of ideas :
-(void)setMaximumLength:(NSInteger)length;{
if ([self length]>length) {
NSLog(#"exxed");
}
}
Please suggest what should I do? I hve one thng in my mind I need to observe the string size but how to do in a category, and which notification will be called?
This sounds suspiciously like formatting for display or processing user input or something like that rather than an actual constraint you want to impose on strings in general. In that case, an NSFormatter class or a bit of code in some specific controller property setter would be a good idea.
But if you really want this to be on the string itself, you either need to provide a method like stringByTruncatingToLength: on NSString or you need to switch to using NSMutableString everywhere, because NSStrings cannot be modified at all and thus a setMaximumLength: method would be kind of meaningless.
The mechanism of truncation can be implemented like this:(for a NSString property of a custom class)
-(void)setName:(NSString*)newName
{
if([newName length]> maxLength)
{
newName = [newName substringWithRange:NSMakeRange([newName length] - maxLength, maxLength];
}
_name = newName;
}

NSTextField delegate notifications -- how to get text?

I've been trying to learn to use Xcode, but I'm getting confused with how to register that NSTextField has changed. Essentially, I have an NSTextField and a button. Clicking the button does stuff with the text in the field. However, I want to be able to get the text of the field without needing to use the text field "Action:send on end editing." That is, I want to be able to enter text and immediately press the button, without hitting enter or tabbing out of the text box. It seems like the way to do this would be by setting a delegate for my NSTextField that responds to
- (void)controlTextDidChange:(NSNotification *)aNotification
But I don't understand how to get the text that has been entered. I assume it has something to do with
[[aNotification userInfo] valueForKey:#"NSFieldEditor"];
but I really have no idea where to go from there.
You're on the right track! The object that you get out of the notification's user info dictionary is the Field Editor, which is simply an NSTextView that's handling the text input on the text field's behalf.
Once you have that object, all you have to do is ask it for its textStorage, which is an NSTextStorage* object holding the text. That object, in turn, has its string which is a plain old NSString holding just the characters.
NSTextView * fieldEditor = [[aNotification userInfo] objectForKey:#"NSFieldEditor"];
NSString * theString = [[fieldEditor textStorage] string];
*A subclass of NSAttributedString, which is an object holding a string and associated "attributes" like color, font, and underlining.
In your button action method, simply read the current string value in the text field:
- (IBAction)didClickTheButton:(id)sender {
NSString* theString = [myTextField stringValue];
// do something with theString
}
If you're only ever handling a single text field, this may be simpler:
- (void)controlTextDidChange:(NSNotification *)obj {
[self.inputField stringValue];
}
I'm totally ignoring all the complicated details of NSText and whatnot and just using the simplicity of the notification being sent and the simplicity of getting the string value from a text field.

Binding returns default value (set with registerDefaults:) instead of zero

Here's my setup:
myTextField is bound to a key in the Shared User Defaults Controller. The user can only enter numbers in the text field.
Each time my application loads, I load default preferences (from the app's Resources folder) using [[NSUserDefaults standardUserDefaults] registerDefaults: ... ].
myMenuItem's title is bound to the same key in the Shared User Defaults Controller.
The issue:
When myTextField is empty, myMenuItem receives the default value that was loaded using registerDefaults: instead of some value that represents the empty field (I would expect 0 or nil).
For example, when the NSTextField is empty the menu item receives "2", the value that was loaded using registerDefaults:, instead of some value that means that the field is empty.
If I comment the registerDefaults: code, the binding returns nil as I would expect when there is nothing in the NSTextField.
I tried to mess around with many of the bindings' settings as well as experiment with placeholder values and I looked at the Cocoa Bindings and User Defaults docs but I could not find the solution.
Expected behavior:
When the text field is empty, I want myMenuItem to reflect that instead of using the default value that was registered using registerDefaults:.
Any help would be greatly appreciated.
I got some hints from the nice folks at irc.freenode.org #macdev and found the following to be the solution to my problem:
Creating a subclass of NSFormatter (or NSNumberFormatter in my case) and overriding getObjectValue:forString:errorDescription: as follows overrides the default behaviour of returning nil (which makes the binding use the registered default value) to instead return 0 when the text field is empty.
- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error {
if ([string isEqualToString:#""]) {
*anObject = [NSNumber numberWithInt:0];
return YES;
} else {
return [super getObjectValue:anObject forString:string errorDescription:error];
}
}
A NSValueTransformer subclass' reverse conversion method would have also worked for this.
Note:
The solution above does not work for strings. That is, if your userDefault value is a string and you've bound that to the value of an NSTextField and you subclass NSFormatter and do this:
- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error {
if ([string isEqualToString:#""]) {
*anObject = nil;
}
return YES;
}
You'll find that when the NSTextField is empty, the binding is set to whatever value you originally registered using -registerDefaults: rather than to an empty string or a nil value. I attempted to use *anObject = [NSNull null]; as well, but that didn't work either --- the binding is still set to the original, default value.
I ended up setting *anObject = #" "; (a string with a single space) in the code above, so that when the textField is empty, the value in the userDefaults pList is set to the string: #" ". I then check for that string everywhere that uses that userDefault value and respond appropriately (ignore the single space and treat it as if the userDefault value were empty).
It's an ugly hack, but the only way I can find to work around this issue currently. I'm posting it here in case someone else stumbles on this thread. If you ask me, binding an NSTextField to a userDefault should bloody well set that userDefault to an empty string when the textField is empty! Why Apple chose to do it the way they did is beyond me.

Binding NSSlider to NSTextField with nil minValue?

I have an NSSlider bound to a text field to display the value given by the slider.
Everything works, but I would like the NSSlider to send "nil" as minValue to the object.
For example, I can convert it to nil when saving (to a propertylist):
if ([myOb intValue] > 0)
[myDict setObject:... forKey:...]
But I would like to apply same behavior when the app is running, cause some other fields are enabled (with binding) only if the value of "myObj" is nil. The problem is the NSSlider always returns "0", and minValue=nil is not accepted by NSSlider.
Thanks in advance,
Ronan.
It won't accept nil as the minValue. The reason, if you look at the NSSlider documentation, is because minValue and maxValue are both defined as doubles, which are not object types.
If you want to customize the value that is displayed in the text field, you would probably want to create an NSValueTransformer subclass to convert double values to NSString values for the text field. Read the Value Transformer Programming Guide for details on how to do this. I have done this in the past so that I can have a label that displays time values similar to the screen saver slider in System Preferences. This works quite well.
Finally i solved my problem, by associate the slider to an IBAction:
- (IBAction)slideValue:(id)sender {
if ([mySlide intValue]==0) { //slider
[myNumBox setStringValue:#""]; //textfield
[myValue setValue:nil]; // value
}
}
So, when the slider is equal to O, it return "" in the textfield (nil don't works).