jampez77 jampez77 - 3 months ago 31
Objective-C Question

Objective-c conditionally add to NSDictionary using BOOL

I'm trying to add objects (Hospitals) into an NSDictionary when the 'pack ID' for the Hospital matches the current one and it is marked as selected.

The selected attribute is a BOOL so I have tried each of the following with no success in the if statement:


  • hospital.selected == TRUE

  • hospital.selected == YES

  • hospital.selected == 1



All of these produce the same results, if selected is equal to 1 or 0 it gets added. they only filter out the nil results.

NSString * NAME = @"name";
NSString * PHONE = @"phone";
NSString * POSTCODE = @"postcode";

NSMutableArray * mArray = [NSMutableArray array];

NSDictionary * dict;

for(ecossHospitalObject *hospital in results){

@try{
NSLog(@"self pack id: %i, hospital pack id: %@", self.fullDataObject.dataPack.pack_id, hospital.dataObject.dataPack.pack_id);
NSLog(@"hospital.selected %hhd", hospital.selected);
if(self.fullDataObject.dataPack.pack_id == [hospital.dataObject.dataPack.pack_id integerValue] && hospital.selected == 1){

dict = [NSDictionary dictionaryWithObjectsAndKeys:
hospital.name, NAME,
hospital.telephone, PHONE,
hospital.postCode, POSTCODE,
nil];

[mArray addObject:dict];
}

}@catch(NSException *e){
NSLog(@"NSException %@", e);
}

}


Where
hospital.selected
is nil I get 0 in the log where it is 0 or 1 I get random numbers (currently 48 and 96 respectively).

The Hospital objects are created using the following method:

+(NSMutableArray*) parseJsonHospitalArray : (NSMutableArray *) jsonArray
{


NSMutableArray *parsedData = [[NSMutableArray alloc] init];


for (id object in jsonArray) {
ecossHospitalObject *hospitalData = [[ecossHospitalObject alloc] init];

hospitalData.address = [object objectForKey:@"address"];
hospitalData.code1 = [object objectForKey:@"code1"];
hospitalData.code2 = [object objectForKey:@"code2"];
hospitalData.distance = [self getIntForString:[object objectForKey:@"distance"]];
hospitalData.hasAE = [[object objectForKey:@"has_a_and_e"] boolValue];
hospitalData.ID = [self getIntForString:[object objectForKey:@"id"]];
hospitalData.latitude = [object objectForKey:@"latitude"];
hospitalData.longitude = [object objectForKey:@"longitude"];
hospitalData.name = [object objectForKey:@"name"];
hospitalData.postCode = [object objectForKey:@"postcode"];
hospitalData.selected = [[object objectForKey:@"selected"] boolValue];
hospitalData.telephone = [object objectForKey:@"telephone"];
hospitalData.website = [object objectForKey:@"website"];


[parsedData addObject: hospitalData];
}

return parsedData;


}


Here is the data printed out:

data: ({
address = nil;
code1 = nil;
code2 = nil;
dataObject = "0x1587d330 <x-coredata://69494056-6039-4679-9C66-7394E9795700/DataObject/p10>";
distance = 0;
"hasA_E" = nil;
hospitalDirectionsArray = nil;
hospitalImageLocation = nil;
iD = 0;
latitude = nil;
longitude = nil;
name = "John Radcliffe Hospital - A & E";
postCode = "OX3 9DU";
selected = nil;
telephone = "01865 741166";
website = nil;
},
{
address = "Headley Way, Headington, Oxford, Oxfordshire";
code1 = RTH08;
code2 = nil;
dataObject = "0x17741940 <x-coredata://69494056-6039-4679-9C66-7394E9795700/DataObject/p10>";
distance = 14;
"hasA_E" = 1;
hospitalDirectionsArray = nil;
hospitalImageLocation = nil;
iD = 645;
latitude = "51.7638761156";
longitude = "-1.2198152232602";
name = "John Radcliffe Hospital - A & E";
postCode = "OX3 9DU";
selected = 1;
telephone = "01865 741166";
website = nil;
},
{
address = "Oxford Rd, Banbury, Oxfordshire";
code1 = RTH05;
code2 = nil;
dataObject = "0x17741940 <x-coredata://69494056-6039-4679-9C66-7394E9795700/DataObject/p10>";
distance = 19;
"hasA_E" = 1;
hospitalDirectionsArray = nil;
hospitalImageLocation = nil;
iD = 623;
latitude = "52.053503457165";
longitude = "-1.3366590559482";
name = "Horton General Hospital - A & E";
postCode = "OX16 9AL";
selected = 0;
telephone = "01295 275500";
website = nil;
},
{
address = "Standing Way, Eaglestone, Milton Keynes, Buckinghamshire";
code1 = RD816;
code2 = nil;
dataObject = "0x17741940 <x-coredata://69494056-6039-4679-9C66-7394E9795700/DataObject/p10>";
distance = 41;
"hasA_E" = 1;
hospitalDirectionsArray = nil;
hospitalImageLocation = nil;
iD = 789;
latitude = "52.026356870309";
longitude = "-0.73577247002525";
name = "Milton Keynes Hospital - A & E";
postCode = "MK6 5LD";
selected = 0;
telephone = "01908 660033";
website = nil;
},
{
address = "Mandeville Road, Aylesbury, Buckinghamshire";
code1 = RXQ02;
code2 = nil;
dataObject = "0x17741940 <x-coredata://69494056-6039-4679-9C66-7394E9795700/DataObject/p10>";
distance = 34;
"hasA_E" = 1;
hospitalDirectionsArray = nil;
hospitalImageLocation = nil;
iD = 1333;
latitude = "51.800759137118";
longitude = "-0.80484777392717";
name = "Stoke Mandeville Hospital - A & E";
postCode = "HP21 8AL";
selected = 0;
telephone = "01296 315000";
website = nil;
}
)

Answer
if(self.fullDataObject.dataPack.pack_id == [hospital.dataObject.dataPack.pack_id integerValue] 
     && hospital.selected == 1){

Stop right there. Never never never never use a comparison test as a conditional. Your code says, in effect:

if (hospital.selected == 1)

That is wrong. So is if (hospital.selected == YES) and if (hospital.selected == TRUE). They are all wrong. They are doomed to failure and random behavior.

If you've set this up correctly, hospital.selected is a boolean. It is a condition. So you just say:

if (hospital.selected)

That is the only way to get the right answer consistently.

EDIT If hospital.selected is an NSNumber wrapping a Bool, then to use it as a conditional, use boolValue — that is, say

if (hospital.selected.boolValue)

This will fail gracefully if the NSNumber is nil, and will work correctly otherwise. But do not assume that it can be only 0 and 1; that is a major mistake.