views:

1067

answers:

4

I am trying to implement this button action, but the if statement is not evaluating to be true. I have a situation where the value in that "School" dictionary will not always have a website stored. For that reason i want to check, but what do i check against. If "nil" is not stored there when there is not a value, then what is?

 -(IBAction) btnVisitWebsite_clicked :(id)sender {

if([School objectForKey:WEBSITE_KEY] == nil){

    UIAlertView *NoWebsite = [[UIAlertView alloc]initWithTitle: @"No Website"
                                                message:@"The selected school has not listed a website"
                                                delegate:self
                                                cancelButtonTitle:@"OK"
                                                otherButtonTitles:nil];

    NoWebsite.tag = 15;
    [NoWebsite show];
    [NoWebsite release];
    NoWebsite = nil;
}

else{

NSMutableString *WebsiteVisit = [[NSMutableString alloc] initWithString: @"http://"];
[WebsiteVisit appendString:[School objectForKey:WEBSITE_KEY]];

[[UIApplication sharedApplication] openURL:[NSURL URLWithString: WebsiteVisit]];


[WebsiteVisit release];

}
}
A: 

An NSDictionary cannot contain nil. If the key exists it has to contain an object. The objectForKey: method will return nil if there is no object defined for a specific key. You can however store [NSNull null] as a null placeholder in a dictionary or array. So you can check for that, it all depends how your dictionary is populated.

[School objectForKey:WEBSITE_KEY] == nil || [School objectForKey:WEBSITE_KEY] == [NSNull null]

Also ensure you're not confusing @"" with a nil or no value. If it's not nil and not [NSNull null] then it's best to log it, and perhaps look at what object is being stored:

NSLog(@"Description: %@", [School objectForKey:WEBSITE_KEY]);
NSLog(@"Class: %@", [[School objectForKey:WEBSITE_KEY] class]);

If the class returns a NSString or NSCFString then it looks like it contains an empty string. Which you can check for. Here is the full blown statement:

id schoolWebsite = School objectForKey:WEBSITE_KEY];
if (schoolWebsite && schoolWebsite != [NSNull null] && [schoolWebsite isKindOfClass:[NSString class]] && [schoolWebsite length] > 0)) {
    // There is definitely a non-empty string for that key!
} else {
    // Not valid
}

This will be good to use as you may be unsure of exactly what is stored in the dictionary as others will be populating it. You can never be too careful!

Michael Waterfall
According to the documentation, if a NSDictionary does not have a value associated with the key, objectForKey: will return nil.
Laurent Etiemble
I would add that you should insert the NSNull object at the point you create the key-value pair in the dictionary. NSNull is an actual object and you treat it just as you would any other value.
TechZen
Yep, that's correct, as mentioned in my answer ;-)
Michael Waterfall
Well for testing purposes right now it's being populated by myself. But when the app is complete it will be getting populated by a server which takes input everyday from office workers.
Makinitez21
Thanks but felix's answered got it
Makinitez21
+1  A: 

Have you tried to use NSLog to print the object for the key ?

NSLog(@"School[WEBSITE_KEY]=<%@>", [School objectForKey:WEBSITE_KEY]);

Maybe it is not nil ?

Laurent Etiemble
tried that, its just a nothing. nothing prints
Makinitez21
If nothing at all prints then the log statement is never executed. If there is nothing following the equal sign then there is an empty string at that position. I.e. ""
Niels Castle
I agree. If nothing prints between the "<>", then you also have to test against an empty string.
Laurent Etiemble
+1  A: 

See if the requested school is in the NSDictionary by checking if it has an entry

BOOL containsKey = [[School allKeys] containsObject:WEBSITE_KEY];

If there is no school website, there should not be an directory entry for the WEBSITE_KEY.

Niels Castle
I created a nice `NSDictionary` category method called `keyExists:` that performs this. Been very handy!
Michael Waterfall
Tried it this way, It evaluated to YES even though nothing was there. I believe the Key will be there, im just tryin to check if a value is there
Makinitez21
Then you probably have an empty string: see my answer for this
Felix
Going for the holistic perspective... If there is no website information for the current school don't stuff an empty string in the dictionary to begin with. You end up carrying bogus data around your app data ecosystem - and performing "wrong" checks.The check here should be "is there a website URL" not "is there a website URL that is not empty"... Usually (and it might not apply to your example) the producer of the dictionary should be responsible for validating the data stuffed in.Anyway, that approach generally works well for me... YMMV.
Niels Castle
+2  A: 

If it is possible that the Website is an empty string you should use the following:

if(![School objectForKey:WEBSITE_KEY] 
   || ([[School objectForKey:WEBSITE_KEY] isKindOfClass:[NSString class]] && [(NSString*)[School objectForKey:WEBSITE_KEY] length]==0)){
    // no website
} else { /* has website*/ }
Felix
Calling the `length` method will crash if the object is not an `NSString` ;-)
Michael Waterfall
I appended a check on the class of the object ;)
Felix
See my answer ;-)
Michael Waterfall
Sorry, didn't see that when posting my answer/edit.
Felix
This worked perfectly
Makinitez21