Why isn't this conditional statement working with NSUserDefault? - iphone

I'm having a problem getting one of my conditional statements to display data correctly. Here is the code I'm working with:
NSUserDefaults *pickerDefaults = [NSUserDefaults standardUserDefaults];
NSString *myString = [pickerDefaults stringForKey:#"userpicker"];
NSString *string = #"Name1";
NSLog(#"%#",myString); //This prints out Name1
NSLog(#"%#",string); //This also prints out Name1
if (myString == string) {
[pickerArray addObject:#"Name Other"];
}
else {
return;
}
I can't get this if statement to add that object to the UIPicker eventhough both strings are equal to each other. However, if I change it to not equal to != then it display's the object in the UIPickerView. I don't understand what I'm doing wrong. Any help would be great. Thanks.

To compare string objects, don't use their pointer values, but compare using
[string isEqualToString:myString]

if (myString == string) // Wrong : It compares address of two NSStrings
if ([myString isEqualToString:string]) // This compares values of NSStrings
{
}

Related

iOS rangeOfString can't locate the string that is definitely there

I am writing code in objective-c. I would like to extract a url from a string.
Here is my code:
NSMutableString *oneContent = [[latestPosts objectAtIndex:i] objectForKey:#"content"];
NSLog(#"%#", oneContent);//no problem
NSString *string = #"http";
if ([oneContent rangeOfString:string].location == NSNotFound) {
NSLog(#"string does not contain substring");
} else {
NSLog(#"string contains substring!");
}
As you can see, I want to extract a url from the oneContent string, and I have checked that oneContent definitely contains "http", but why does the result show nothing?
Is there some better way to extract the url?
Check oneContent or the actual code you are running.
This works:
NSMutableString *oneContent = [#"asdhttpqwe" mutableCopy];
NSLog(#"%#", oneContent);//no problem
NSString *string = #"http";
if ([oneContent rangeOfString:string].location == NSNotFound) {
NSLog(#"string does not contain substring");
} else {
NSLog(#"string contains substring!");
}
NSLog output:
Untitled[5911:707] asdhttpqwe
Untitled[5911:707] string contains substring!
It is probably best not to use a Mutable string unless there is some substantial reason to do so.
I would suggest using NSScanner.

Why is my strcmp always returning true?

I'm trying to compare user text input from an iphone app with the text in a static array I have declared. It is always returning "true", even when the text is different. After doing the strncmp, I display both text fields. To the human eye, they are what I expect the fields to be. The debugmsg I return to the screen shows what I expect the values to be, but the compare is always coming up true. Any suggestions would be appreciated. Thanks.
if (strncmp(SymbolEntered.text,
[NSString stringWithCString:elements_table2[idx].element_symbol],2)==0)
{
DebugMsg.text = [NSString stringWithCString:"Correct answer"];
}
else
{
DebugMsg.text = [NSString stringWithCString:"Incorrect!"];
}
DebugMsg2.text = SymbolEntered.text;
DebugMsg3.text = [NSString stringWithCString:elements_table2[idx].element_symbol];
You really should do this with NSString, which has tons of comparison methods implemented, instead of CString (why are you using CString?). strcmp doesn't work with NSString.
if([SymbolEntered.text isEqualToString:[NSString stringWithCString:elements_table2[idx].element_symbol]]) {
DebugMsg.text = #"Correct answer";
} else {
DebugMsg.text = #"Incorrect answer";
}
Also instead of:
DebugMsg.text = [NSString stringWithCString:"Correct answer"];
you can do this:
DebugMsg.text = #"Correct answer";

how to check if NSString = a specific string value?

Hi I am woundering if you can check to see if a NSString equals a specific value say for instance a name of a person?
I am thinking along the lines of
if (mystring == #"Johns"){
//do some stuff in here
}
if ([mystring isEqualToString:#"Johns"]){
//do some stuff in here
}
Here is another method you might want to use in some circumstances:
NSArray * validNames = #[ #"foo" , #"bar" , #"bob" ];
if ([validNames indexOfObject:myString].location != NSNotFound)
{
// The myString is one of the names in the valid names array
}
Or if you have a large amount of names in the array you could use a NSSet, since finding an object is faster than in an array ((O(Log N) vs O(N))
NSSet * validNamesSet = [NSSet setWithArray:validNames];
if ([validNamesSet containsObject:myString])
{
// This is faster than indexOfObject for large sets
}
These methods work because NSSet and NSArray use isEqual: which will call isEqualToString: for NSString instances.

Check if key exists in NSDictionary is null or not

I did search on how to check if NSDictionary key exists or not and came up with the solution. But still it throws me an error saying adding null value to the key.
I am not sure if my code is correct or not. If anyone has any idea about this can help me.
NSDictionary *result;
id myImageURL = [result objectForKey:#"url"];
if ((NSNull *)myImageURL == [NSNull null])
myImageURL = #"";
id myImage = [result objectForKey:#"image"];
if ((NSNull *)myImage == [NSNull null])
myImage = #"";
Check if null add nothing and if not add the value. But it still gives me an error dont know why.
/****OUTPUT*****/
2011-08-11 14:56:06.668 Tab_Table_Win[6510:207] RESULTS : {
image = "<UIImage: 0xbc332c0>";
url = "http://a3.twimg.com/profile_images/999228511/normal.jpg";
}
2011-08-11 14:56:06.669 Tab_Table_Win[6510:207] url : http://a3.twimg.com/profile_images/999228511/normal.jpg
2011-08-11 14:56:06.670 Tab_Table_Win[6510:207] IMage : <UIImage: 0xbc332c0>
/*****Breaks Here ***/
2011-08-11 14:56:06.876 Tab_Table_Win[6510:207] RESULTS : {
}
2011-08-11 14:56:06.878 Tab_Table_Win[6510:207] url : (null)
2011-08-11 14:56:06.879 Tab_Table_Win[6510:207] IMage : (null)
2011-08-11 14:56:06.881 Tab_Table_Win[6510:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil key'
Correct answer is :
NSDictionary *result;
NSURL *myImageURL = [result objectForKey:#"url"];
UIImage *myImage = [result objectForKey:#"image"];
/**** Correct way ****/
if (myImageURL != nil && myImage != nil) {
[images setObject:myImage forKey:myImageURL];
}
Thank you for all the explanation.
Tommy explained this perfectly.
What I recommend is create an extension of the NSDictionary class like:
#import <Foundation/Foundation.h>
#interface NSDictionary (Safety)
- (id)safeObjectForKey:(id)aKey;
#end
And the implementation file:
#import "NSDictionary+Safety.h"
#implementation NSDictionary (Safety)
- (id)safeObjectForKey:(id)aKey {
NSObject *object = self[aKey];
if (object == [NSNull null]) {
return nil;
}
return object;
}
#end
And instead of using [dictionary objectForKey:#"keyName"]; in your code, use
[dictionary safeObjectForKey:#"keyName"];
This way, as Tommy explained, you'd be sending a method call to a nil which wouldn't crash the app but your object would get a nil value.
Hope this helps.
Whenever I try to check if an object being returned from a dictionary is null, I do this:
id obj = [myDictionary objectForKey:entityKeyName];
if (obj == [NSNull null]) {
// do something
}
Then in your code, it would be:
NSDictionary *result;
NSString *myImageURL = [result objectForKey:#"url"];
if (myImageURL == [NSNull null])
myImageURL = #"";
That's what I would do in your code.
Also, just making sure, is the NSDictionary result defined? In your code, it doesn't have anything it's being set to. It's just being defined as variable you plan on using called results
the answer below worked for me:
https://stackoverflow.com/a/2784675/936957
if ([dictionary objectForKey:key]) {
// previously stored data for "key"
}
Also note that you can get array of the keys in a dictionary using
[dictionary allKeys]
If an object doesn't exist for a key, NSDictionary will return nil. An NSNull is an actual object, and therefore a distinct thing. It's like the distinction between being able to record that there was a value and the value as null, and not recording whether there was a value. It also rests a bit on you thinking in C terms of the indirection of a pointer to an object rather than just an object, so it's not completely semantically pleasing from that perspective.
In Objective-C, you may send any message to nil and the result is guaranteed to be nil (or 0). So if your code is designed to ensure that you have a safe object reference, as you might in C++, then what you're doing is unnecessary. Compound statements like:
object = [[Type alloc] init];
Are always explicitly safe, even if alloc fails and returns nil. All that'll happen is that the call to init won't do anything at all, and object will end up with the value nil because the result of sending of init to nil is also nil.
That being said, the answers provided by Bill and Emmanuel should be correct. Compare your result either directly to nil or implicitly to zero. If you're getting a crash later on, I'll guess it's because you're expecting myImageUrl and myImage to be types other than NSString (I notice you've used the typeless id in your original code) and sending them a message they don't respond to.
NSDictionary *result;
NSString *myImageURL = [result objectForKey:#"url"];
if (myImageURL == NULL)
myImageURL = #"";
NSString *myImage = [result objectForKey:#"image"];
if (myImageURL == NULL)
myImage = #"";
See if that works, rather than overthinking the NULL class.
this another option:
if (![result objectForKey:#"image"])
{
NSLog(#"doesn't exist");
}
if ([result objectForKey:#"image"])
{
NSLog(#"exist");
}
that was not work for me, i figured it out like this
id myImageURL = [result objectForKey:#"url"];
if ([myImageURL isKindOfClass:[NSNull class]])
myImageURL = #"";
Alright here's the actual answer which #Iomec almost had
UIImage *myImage = ([result objectForKey:#"image"] != [NSNull null] ? [result objectForKey:#"image"] : nil);
That is the actual correct answer because, it comes as null and when you say myImage = [receivedObject...]; then if myImage = nil, you are in effect casting a null value(nil) into a class which is an exception, if not a running bug.
You should:
1) test for NSNull null value
2) if not nil then assign
If you code hasn't bugged out yet, it will in production when you have 8 apps running in the background one day.
I got the same issue with JSONKit. The implementation there is
- (id)objectForKey:(id)aKey
{
[...]
return((entryForKey != NULL) ? entryForKey->object : NULL);
}
So this will definitely return NULL if the object isn't there. I check it like the following
NSArray* array = [myDictionary objectForKey:#"a"];
if((NSNull*)arrays!=[NSNull null])
{
[...]
}
1. Results Dictionary after JSON parsing:
//if hits success
{"result":{"action":"authentication","statusCode":"200","statusMsg":"No
error, operation
successful.","count":1,"data":{"apiToken":"509e6d21-4f69-4ded-9f3d-4537e59e6a3a","userId":8,"role":"Bidder","firstName":"bidder","lastName":"bidder","emailAddress":"1cbrecbill#wricapitalgroup.com","countiesCovered":"21,16,11,1,2,14,32,3,4,25,13,15,5,41,43,6,12,7,24,39,17,36,42,44,29,40,8,18,19,27,9,28,23,10,33,26,35,20,30,22,34,31"}}}
//Data is Dictionary inside Result
-----------------------------------------------------------------------
I had an error showing : NULL DATACould not cast value of type 'NSNull' (0xda7058) to 'NSDictionary' (0xda6d74) and the result was
the following.
({"result":{"action":"authentication","statusCode":"204","statusMsg":"Invalid
Username or Password","count":null,"data":null}})
I fixed the Null check of dictionary.
if (result.objectForKey("data") is NSNull)
{
print ("NULL DATA")
}
else
{
let data = result["data"]as! NSDictionary
print (data)
}
Might want to add a bit more safety by checking to make sure it is NOT a string instead of just checking if it IS a nil. (To make sure it is not a number or anything else you might not want.)
id myImageURL = [result objectForKey:#"url"];
if (![myImageURL isKindOfClass:[NSString class]]) {
myImageURL = #"";
}
When you call objectForKeyin nullable dictionary, app gets crashed so I fixed this from this way to avoid from crash.
- (instancetype)initWithDictionary:(NSDictionary*)dictionary {
id object = dictionary;
if (dictionary && (object != [NSNull null])) {
self.name = [dictionary objectForKey:#"name"];
self.age = [dictionary objectForKey:#"age"];
}
return self;
}

NSString contains : <null> and is crashing my app

I've an NSString thats populated from some data returned via JSON.
The code works great under normal circumstances but there is an occasion when i get returned by the JSON.
When i do a check to see if my NSString == nil or == null it fails the test.
But the fact that the NSString contains crashes my app.
So does have some special meaning in Objective C? Or should i just do a string compare and see if the string is equal to rather than being nil and handle it that way.
This has me a little confused.
Many Thanks,
Code
<null> is what NSNull returns for its -description method. You need to also check for
myString == [NSNull null]
in this case.
Additional info: IIRC the common Objective-C JSON stuff will use [NSNull null] for nulls in the JSON structure, to differentiate the value from one that simply isn't there.
NSString * is just a pointer to a NSString object.
To test for null pointer:
NSString *str;
if (str) {
// str points to an object
if ([str length] == 0) {
// string is empty
}
} else
// str points to nothing
}
If you want to check for whitespace, you can trim the NSString with stringByTrimmingCharactersInSet.
You could check to see if it's null by.
if ([str isKindOfClass:[NSNull class]]) {
// str is null.
}
I did it this way:
if([string isKindOfClass:[NSNull class]]) {
NSLog(#"This is JSON null");
} else {
NSLog(#"This is a string, do what you wanna do with it");
}