If UITextField or NSString is empty - iphone

If I want to check whether a UITextField or NSString is empty, can I compare it with NULL or nil?

Neither of the methods you suggest are foolproof. The best tests are:
if ([myTextField.text length] > 0) ...
or
if ([myString length] > 0) ...

if i want to check whether a textfield or string is empty i compare it with NULL or nil?
No.
An empty string object (a string object containing no characters) or a text-field object containing an empty string object is not the same as nil, which is no object at all. You need to ask the (text field's) string how long it is, or ask it whether it is equal to an empty string you have on hand (#"").
NULL, while also a null pointer, should be used for general pointers, not pointers to Objective-C instances (for which you have the more specific nil) or classes (for which you have the more specific Nil).

I had a similar problem but no method other than this worked for me:
NSString *string = textfield.text;
if ([string isEqualToString:#""]) {
....
}

Related

NSString or NSCFString in xcode?

I m taking a NSMutabledictionary object in NSString like this :
NSString *state=[d valueForKey:#"State"];
Now sometimes state may be null and sometimes filled with text.So Im comparing it.While comparing state becomes NSString sometimes and NSCFString othertimes..So unable to get the desired result..
if([state isEqualToString#""])
{
//do something
}
else
{
//do something
}
So while comparing it is returning nil sometimes.So immediately jumping into the else block.
I need a standard way to compare if the state is empty whether it is a NSString or NSCFString ...
How can I do it?
If you're unable to get the result you want, I can assure you it's not because you get a NSCFString instead of a NSString.
In Objective-C, the framework is filled with cluster classes; that is, you see a class in the documentation, and in fact, it's just an interface. The framework has instead its own implementations of these classes. For instance, as you noted, the NSString class is often represented by the NSCFString class instead; and there are a few others, like NSConstantString and NSPathStore2, that are in fact subclasses of NSString, and that will behave just like you expect.
Your issue, from what I see...
Now sometimes state may be null and sometimes filled with text.
... is that in Objective-C, it's legal to call a method on nil. (Nil is the Objective-C concept of null in other languages like C# and Java.) However, when you do, the return value is always zeroed; so if you string is nil, any equality comparison to it made with a method will return NO, even if you compare against nil. And even then, please note that an empty string is not the same thing as nil, since nil can be seen as the absence of anything. An empty string doesn't have characters, but hey, at least it's there. nil means there's nothing.
So instead of using a method to compare state to an empty string, you probably need to check that state is not nil, using simple pointer equality.
if(state == nil)
{
//do something
}
else
{
//do something
}
You can do this
if([state isEqualToString:#""])
{
//do something
}
else
{
//do something
}
You must have to type cast it to get the correct answer.
NSString *state = (NSString *) [d valueForKey:#"State"];
if(state != nil)
{
if(state.length > 0)
{
//string contains characters
}
}

NSString internals - how does length works?

I've a question about NSString internals.
I want to check a string length and basically I wanted to know if a NSString knows its length / count each time / count & cache the result.
Should I store it's length and compute or call the length method each time ?
To test a string I can test against nil OR ask for it's length.
if (str != nil) {
// compute
}
if ([str length]) {
// compute
}
Which one is the fastest ?
Which one is the more memory efficient ?
Thanks
Checking for nil ("no object") is most definitely not the same as sending the length message to the (NSString) object. Only one of the conditional checks is valid to test for an "empty" string. (An "empty" string is an object and, therefore, not nil.)
The bigger question is: does NSString store a length or is it sentinel-terminated (like a "normal c string")? NSString stores the length as an internal property so it, length, is as O(1) operation.
Happy coding.
Here is how CFStringGetLength works:
(from http://opensource.apple.com/source/CF/CF-550.43/CFString.c)
/* Returns length; use __CFStrLength2 if contents buffer pointer has already been computed.
*/
CF_INLINE CFIndex __CFStrLength(CFStringRef str) {
if (__CFStrHasExplicitLength(str)) {
if (__CFStrIsInline(str)) {
return str->variants.inline1.length;
} else {
return str->variants.notInlineImmutable1.length;
}
} else {
return (CFIndex)(*((uint8_t *)__CFStrContents(str)));
}
}
So it should be O(1) for all cases.
The two -- testing a NSString pointer for nil and testing the length of an NSString -- are not in any way equivalent. An NSString object with a zero length can exist, and a pointer to it will not compare equal to nil.
To my knowledge (and I'd be quite surprised to discover I was wrong), the length of an NSString is stored within the object as an efficiently-referenced property. Caching the length would generally be unnecessary complexity.
NSString is immutable class, so the length stays the same all of the time.
Addendum: Testing against [string length] evaluates to 0/nil/NO in both cases (string being nil and string having zero length).

Objective C: Compare Array Element to String

Greetings,
I'm trying to simply compare a NSString to an NSArray.
Here is my code:
NSString *username=uname.text;
NSString *regex=#"^[a-zA-Z0-9-_.]{3,20}$";
NSArray *matchArray=nil;
matchArray=[username componentsMatchedByRegex:regex];
if(matchArray[0] == "asdf"){ //this line causes the problem!
NSLog(#"matchArray %#",matchArray);
}
I get an "invalid operands to binary ==" error.
How can I compare the string?
Many thanks in advance,
You are trying to compare an NSString to a C string (char *), which is wrong. matchArray is an NSArray so you cannot treat it as a C array either, you have to use its objectAtIndex: method and pass in the index.
Use this instead:
if ([[matchArray objectAtIndex:0] isEqualToString:#"asdf"]) {
NSLog(#"matchArray %#", matchArray);
}
Addressing your comments, the reason why isEqualToString: does not show up in autocomplete is because Xcode cannot guess that matchArray contains NSStrings (it only knows it contains ids, that is, arbitrary Objective-C objects). If you really wanted to be sure, you can perform an explicit cast, but it doesn't matter if you don't:
if ([(NSString *)[matchArray objectAtIndex:0] isEqualToString:#"asdf"]) {
NSLog(#"matchArray %#", matchArray);
}
you want to use -objectAtIndex to get the array element. NOT the C array accessor syntax
try to use:
[[matchArray objectAtIndex:0] isEqualToString:#"asdf"];
anyway the string "asdf" should be #"asdf"

ObjectiveC Parse Integer from String

I'm trying to extract a string (which contains an integer) from an array and then use it as an int in a function. I'm trying to convert it to a int using intValue.
Here's the code I've been trying.
NSArray *_returnedArguments = [serverOutput componentsSeparatedByString:#":"];
[_appDelegate loggedIn:usernameField.text:passwordField.text:(int)[[_returnedArguments objectAtIndex:2] intValue]];
I get this error:
passing argument 3 of 'loggedIn:::' makes pointer from integer
without a cast
What's wrong?
I really don't know what was so hard about this question, but I managed to do it this way:
[myStringContainingInt intValue];
It should be noted that you can also do:
myStringContainingInt.intValue;
You can just convert the string like that [str intValue] or [str integerValue]
integerValue
Returns the NSInteger value of the receiver’s text.
(NSInteger)integerValue
Return Value
The NSInteger value of the receiver’s text, assuming a decimal representation and skipping whitespace at the beginning of the string. Returns 0 if the receiver doesn’t begin with a valid decimal text representation of a number.
for more information refer here
NSArray *_returnedArguments = [serverOutput componentsSeparatedByString:#":"];
_returnedArguments is an array of NSStrings which the UITextField text property is expecting. No need to convert.
Syntax error:
[_appDelegate loggedIn:usernameField.text:passwordField.text:(int)[[_returnedArguments objectAtIndex:2] intValue]];
If your _appDelegate has a passwordField property, then you can set the text using the following
[[_appDelegate passwordField] setText:[_returnedArguments objectAtIndex:2]];
Basically, the third parameter in loggedIn should not be an integer, it should be an object of some kind, but we can't know for sure because you did not name the parameters in the method call. Provide the method signature so we can see for sure. Perhaps it takes an NSNumber or something.
Keep in mind that international users may be using a decimal separator other than . in which case values can get mixed up or just become nil when using intValue on a string.
For example, in the UK 1.23 is written 1,23, so the number 1.777 would be input by user as 1,777, which, as .intValue, will be 1777 not 1 (truncated).
I've made a macro that will convert input text to an NSNumber based on a locale argument which can be nil (if nil it uses device current locale).
#define stringToNumber(__string, __nullable_locale) (\
(^NSNumber *(void){\
NSLocale *__locale = __nullable_locale;\
if (!__locale) {\
__locale = [NSLocale currentLocale];\
}\
NSString *__string_copy = [__string stringByReplacingOccurrencesOfString:__locale.groupingSeparator withString:#""];\
__string_copy = [__string_copy stringByReplacingOccurrencesOfString:__locale.decimalSeparator withString:#"."];\
return #([__string_copy doubleValue]);\
})()\
)
If I understood you correctly, you need to convert your NSString to int? Try this peace of code:
NSString *stringWithNumberInside = [_returnedArguments objectAtIndex:2];
int number;
sscanf([stringWithNumberInside UTF8String], "%x", &flags);

NSString question - rangeOfString method

I am having an issue that I can't figure out.
I'm trying to run the rangeOfString method on a string, and I'm not sure how to determine if the string was not found. For example:
NSRange range = [#"abc" rangeOfString:#"d" options:NSCaseInsensitiveSearch range:NSMakeRange(0,3)];
Clearly, "d" is not contained in the string "abc." I'd like to be able to do this:
if(the range is empty since "d" is not in "abc")
//do something
What is the code for this?
Thanks!!
From the documentation of NSString
-[NSString rangeOfString]
Return Value
An NSRange structure giving the
location and length in the receiver of
the first occurrence of aString.
Returns {NSNotFound, 0} if aString is
not found or is empty (#"").
So it looks like:
if ([#"abc" rangeOfString:#"d"].location == NSNotFound){
//Do something
Is the Apple-approved way.
EDIT:
I made a really bad typo, fixed it, thanks Kalle.
Check the length of the range. If it's non-zero, it was found.