NSDictionary *regionDict = (NSDictionary *) region;
NSNumber *lat = [regionDict objectForKey:#"lat"];
//[latitude addObject:lat];
NSNumber *lng = [regionDict objectForKey:#"lng"];
//[longitude addObject:lng];
NSLog(#"%#%#%#",lat,lng,titles);
if(lat == [NSNumber numberWithFloat:0.00] && lng == [NSNumber numberWithFloat:0.00])
{
NSLog(#"%#%#%#",lat,lng,titles);
}
else
{
CLLocationCoordinate2D coord;
coord.latitude =lat.doubleValue;
coord.longitude =lng.doubleValue;
MapViewAnnotation *annotation =[[MapViewAnnotation alloc]initWithTitle:titles AndCoordinate:coord];
[self.mapView addAnnotation:annotation];
}
if condition is not satisfied because of NSNumber not check with null value.
what is the way i can check?
Tell me possible ways.. for checking null.
You can check if an object is null by doing
if ([myObject isKindOfClass:[NSNull class]])
But if you want to check if a float boxed in a NSNumber is zero, you can do
if (lng.floatValue == 0. && lat.floatValue == 0)
I've been checking if NSDecimalNumber was null using:
if (decimalNumber == nil)
This is working great for me.
NSDictionary *regionDict = (NSDictionary *) region;
NSNumber *lat;
if([regionDict objectForKey:#"lat"] == [NSNull null])
{
lat = 0;
}
else
{
lat = [regionDict objectForKey:#"lat"];
}
NSNumber *lng;
if([regionDict objectForKey:#"lng"] == [NSNull null] )
{
lng=0;
}
else
{
//[latitude addObject:lat];
lng = [regionDict objectForKey:#"lng"];
}
//[longitude addObject:lng];
if(lat.floatValue == 0.00 && lng.floatValue == 0.00)
{
NSLog(#"%#%#%#",lat,lng,titles);
}
else
{
NSLog(#"%#%#%#",lat,lng,titles);
CLLocationCoordinate2D coord;
coord.latitude =lat.doubleValue;
coord.longitude =lng.doubleValue;
MapViewAnnotation *annotation =[[MapViewAnnotation alloc]initWithTitle:titles AndCoordinate:coord];
[self.mapView addAnnotation:annotation];
}
I'm not quite clear what you want to check. Depending on your JSON data, you will get one of the following:
myObject == nil - the object isn't there at all.
myObject == [NSNull null] - the JSON data is "null" without the quotes
myObject.doubleValue == 0.0 - the JSON data contained a number 0 or 0.0
Note that trying to read doubleValue will crash if the JSON data was "null", so that needs checking first. Comparing
myObject == [NSNumber numberWithDouble:0.0]
isn't going to work, because that just compares object pointers. Would be a very huge coincidence if this was actually the same object.
[obj isKindOfClass:[NSNull class]]
Related
This question already has answers here:
Determine if NSNumber is NaN
(9 answers)
Closed 9 years ago.
I have an NSMutableArray with 1 float value and 4 nan values. I want to execute some operations if the array object is nan. How can I write an if condition?
try isnan function
Iterate your array and put check
isnan([[Array objectAtIndex:i] floatValue])
(dont forget to add math.h library)
NSNumber *num = //your number;
float value = [num floatValue];
if (isnan(value))
{
NSLog(#"is nan");
}
Do something like this:
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:[NSNumber numberWithFloat:1.0]];
[array addObject:[NSNull null]];
[array addObject:[NSNull null]];
[array addObject:[NSDecimalNumber notANumber]];
BOOL foundNull = NO;
for (id value in array) {
if (!value || value == [NSNull null]) {
foundNull = YES;
} else if ([value isKindOfClass:[NSDecimalNumber class]]) {
if ([value isEqualToNumber:[NSDecimalNumber notANumber]]) {
foundNull = YES;
}
}
}
NSLog(#"Found null/NaN: %i", foundNull);
You can also use
[NSDecimalNumber notANumber] method to compare and check if this a valid number or not.
I need to know whatever an int64_t has decimals, and how many. This should be placed in if-else-statement. I tried this code, but it causes the app to crash.
NSNumber *numValue = [NSNumber numberWithInt:testAnswer];
NSString *string = [numValue stringValue];
NSArray *stringComps = [string componentsSeparatedByString:#"."];
int64_t numberOfDecimalPlaces = [[stringComps objectAtIndex:1] length];
if (numberOfDecimalPlaces == 0) {
[self doSomething];
} else {
[self doSomethingElse];
}
Your question doesn't make a lot of sense; you are creating the NSNumber object from an int so it will never have decimal places, as an int cannot store them. The reason your code is crashing is that it assumes that the array of components is always at least 2 elements long (as you use objectAtIndex:1).
This is better, though still not that good:
NSString *answer = ...; // From somewhere
NSArray *stringComps = [answer componentsSeparatedByString:#"."];
if ([stringComps count] == 0) {
[self doSomething];
} else if [stringComps count] == 1) {
[self doSomethingElse];
} else {
// Error! More than one period entered
}
This still isn't a very good test as it only tests if a period (.) has been entered, not a valid number.
I want to sort a NSMutableArray, where each row is a NSMutableDictionary, with my GPS position from CoreLocation framework.
This is an example of my array of POI
arrayCampi = (
{
cap = 28100;
"cell_phone" = "";
championship = "IBL 1D";
citta = Novara;
division = "";
email = "";
fax = 0321457933;
indirizzo = "Via Patti, 14";
latitude = "45.437174";
league = "";
longitude = "8.596029";
name = "Comunale M. Provini";
naz = Italy;
prov = NO;
reg = Piemonte;
sport = B;
surname = "Elettra Energia Novara 2000";
telefono = 03211816389;
webaddress = "http://www.novarabaseball.it/";
})
I need to sort this array with my location (lat and long) with field 'latitude' and 'longitude' of each row in ascending mode (first row is POI nearest to me).
I have tried this solution without success:
+ (NSMutableArray *)sortBallparkList:(NSMutableArray *)arrayCampi location:(CLLocation *)myLocation {
if ([arrayCampi count] == 0) {
return arrayCampi;
}
if (myLocation.coordinate.latitude == 0.00 &&
myLocation.coordinate.longitude == 0.00) {
return arrayCampi;
}
NSMutableArray *sortedArray = [NSMutableArray arrayWithArray:arrayCampi];
BOOL finito = FALSE;
NSDictionary *riga1, *riga2;
while (!finito) {
for (int i = 0; i < [sortedArray count] - 1; i++) {
finito = TRUE;
riga1 = [sortedArray objectAtIndex: i];
riga2 = [sortedArray objectAtIndex: i+1];
CLLocationDistance distanceA = [myLocation distanceFromLocation:
[[CLLocation alloc]initWithLatitude:[[riga1 valueForKey:#"latitude"] doubleValue]
longitude:[[riga1 valueForKey:#"longitude"] doubleValue]]];
CLLocationDistance distanceB = [myLocation distanceFromLocation:
[[CLLocation alloc]initWithLatitude:[[riga2 valueForKey:#"latitude"] doubleValue]
longitude:[[riga2 valueForKey:#"longitude"] doubleValue]]];
if (distanceA > distanceB) {
[riga1 retain];
[riga2 retain];
[sortedArray replaceObjectAtIndex:i+1 withObject:riga2];
[sortedArray replaceObjectAtIndex:i withObject:riga1];
[riga1 release];
[riga2 release];
finito = FALSE;
}
}
}
return sortedArray;
}
Can anyone help me, also with other solution?
Alex.
Sorting by lat and long will not give you the nearest location from any given coordinates. As an approximation*) you could use Pythagoras (you learned that in high school, remember?):
float distance = sqrtf(powf((origLat-destLat),2)+powf((origLon-destLon), 2));
Simply add that to your dictionary with key #"distance" and sort with
NSArray *sorted = [arrayOfDictionaries sortedArrayUsingDescriptors:
#[[NSSortDescriptor sortDescriptorWithKey:#"distance" ascending:YES]]];
*) It's an approximation because theoretically distance between two points is a curved line on the surface of an ellipsoid.
[arrayCampi sortedArrayUsingSelector:#selector(compare:)];
- (NSComparisonResult)compare:(NSDictionary *)otherObject {
if ([[self objectForKey:#"key"] isEqual:[otherObject objectForKey:#"key"]]) {
return NSOrderedSame;
}
else if (//condition) {
return NSOrderedAscending;
}
else {
return NSOrderedDescending;
}
}
Take a look at How to sort an NSMutableArray with custom objects in it?
I think there's no need to implement your own sorting algorithm. There are the ready ones out there :-) I would suggest to look at NSSortDescriptor.
And since you keep your geo coordinates in NSString format, and not the NSNumber, you probably would need to write your own NSPredicate for NSString objects comparison in your class. (I don't remember if #"123" is greater than #"1.23", I mean special symbol '.')
I am loading a map view. And I am adding pins to the map, based on address of the contacts in address book. I am having some strange cases where some pins(maybe 2 out of 10) don't drop in the map view . I have checked the address, which is valid. But the pin is not dropping. What could be the reason for this.
for (i = 0; i<[groupContentArray count]; i++) {
person = ABAddressBookGetPersonWithRecordID(addressbook,[[groupContentArray objectAtIndex:i] intValue]);
ABMultiValueRef addressProperty = ABRecordCopyValue(person, kABPersonAddressProperty);
NSArray *address = (NSArray *)ABMultiValueCopyArrayOfAllValues(addressProperty);
NSLog(#"Address %#", address);
for (NSDictionary *addressDict in address)
{
addAnnotation = nil;
firstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
lastName = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
NSString *country = [addressDict objectForKey:#"Country"];
NSString *streetName = [addressDict objectForKey:#"Street"];
NSString *cityName = [addressDict objectForKey:#"City"];
NSString *stateName = [addressDict objectForKey:#"State"];
if (streetName == (id)[NSNull null] || streetName.length == 0 ) streetName = #"";
if (stateName == (id)[NSNull null] || stateName.length == 0 ) stateName = #"";
if (cityName == (id)[NSNull null] || cityName.length == 0 ) cityName = #"";
if (country == (id)[NSNull null] || country.length == 0 ) country = #"";
NSString *fullAddress = [streetName stringByAppendingFormat:#"%#/%#/%#", cityName, stateName, country];
mapCenter = [self getLocationFromAddressString:fullAddress];
if(stateName != NULL || country != NULL || streetName != NULL || cityName != NULL){
if ((mapCenter.latitude == 0) && (mapCenter.longitude == 0))
{
// Alert View
}
else{
addAnnotation = (MyAddressAnnotation *)[mapView dequeueReusableAnnotationViewWithIdentifier:[groupContentArray objectAtIndex:i]];
if(addAnnotation == nil){
addAnnotation = [[[MyAddressAnnotation alloc] initWithCoordinate:mapCenter title:firstName SubTitle:lastName Recordid:[groupContentArray objectAtIndex:i] ]autorelease];
[mapView addAnnotation:addAnnotation];}
}
}
}
CFRelease(addressProperty);
}
Edit: I am editing my question and be more specific. I am using the code to drop pins on my mapView. On my Mac PC, if there are 20 pins to be dropped in the map. All the 20 pins are dropping accurately and working fine. But when I am using IPhone or IPad, the pin count reduces massively. That is, out of some 20 pins I am dropping, only 4 pins are showing on the map. I am not able to figure out a reason for this.
This code:
else {
addAnnotation = (MyAddressAnnotation *)[mapView dequeueReusableAnnotationViewWithIdentifier:[groupContentArray objectAtIndex:i]];
if (addAnnotation == nil) {
addAnnotation = [[[MyAddressAnnotation alloc] initWithCoordinate:mapCenter title:firstName SubTitle:lastName Recordid:[groupContentArray objectAtIndex:i] ]autorelease];
[mapView addAnnotation:addAnnotation];
}
}
makes no sense.
The dequeueReusableAnnotationViewWithIdentifier method is for dequeuing MKAnnotationView objects -- not id<MKAnnotation> objects.
The dequeuing code belongs in the viewForAnnotation delegate method anyway, not here.
Here, you should just create your annotation objects (MyAddressAnnotation) and call addAnnotation on them.
I also highly recommend you change the name of your annotation variable from addAnnotation to something else so you can't confuse it with the map view's method addAnnotation.
My bad. In the "fulladdress" string(between streetName and cityName) that I use, were not separated by a space or "," or "/". Therefore some of the addresses were not being recognised.
I have been working on an iPhone app, where-in i have list of users in a NSMutableArray like below.
myMutableArray: (
{
FirstName = Getsy;
LastName = marie;
Latitude = "30.237314";
Longitude = "-92.461008";
},
{
FirstName = Angel;
LastName = openza;
Latitude = "30.260329";
Longitude = "-92.450414";
},
{
FirstName = Sara;
LastName = Hetzel;
Latitude = "30.2584499";
Longitude = "-92.4135357";
}
)
I need to sort users based on the location who is nearby to my location by calculating latitude and longitude. I am not able to achieve this till now. Could someone help me on giving some samples?
UPDATED: I am trying like below as per Mr.sch suggested. Please check my updated code. Is it fine?.
NSArray *orderedUsers = [myMutableArray sortedArrayUsingComparator:^(id a,id b) {
NSArray *userA = (NSArray *)a;
NSArray *userB = (NSArray *)b;
CGFloat aLatitude = [[userA valueForKey:#"Latitude"] floatValue];
CGFloat aLongitude = [[userA valueForKey:#"Longitude"] floatValue];
CLLocation *participantALocation = [[CLLocation alloc] initWithLatitude:aLatitude longitude:aLongitude];
CGFloat bLatitude = [[userA valueForKey:#"Latitude"] floatValue];
CGFloat bLongitude = [[userA valueForKey:#"Longitude"] floatValue];
CLLocation *participantBLocation = [[CLLocation alloc] initWithLatitude:bLatitude longitude:bLongitude];
CLLocation *myLocation = [[CLLocation alloc] initWithLatitude:locationCoordinates.latitude longitude:locationCoordinates.longitude];
CLLocationDistance distanceA = [participantALocation distanceFromLocation:myLocation];
CLLocationDistance distanceB = [participantBLocation distanceFromLocation:myLocation];
if (distanceA < distanceB) {
return NSOrderedAscending;
} else if (distanceA > distanceB) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}];
Thank you!
NSArray *orderedUsers = [users sortedArrayUsingComparator:^(id a,id b) {
User *userA = (User *)a;
User *userB = (User *)b;
CLLocationDistance distanceA = [userA.location getDistanceFromLocation:myLocation];
CLLocationDistance distanceB = [userB.location getDistanceFromLocation:myLocation];
if (distanceA < distanceB) {
return NSOrderedAscending
} else if (distanceA > distanceB) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}];
First thing, you will need to calculate the distance between your current location and the location of each other user.
Talking mathematically, here is a Wolfram|Alpha example
Now "programmatic-ally", you can use CLLocation class, here is an example:
(CLLocationDistance)getDistanceFrom:(const CLLocation *)location
But first you will need to create the location object from your Latitude and Longitude. You can use:
(id)initWithLatitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude
You can calculate the distance (geographical, not flat plane!) between your position and each of these items' positions and order by that value.
- (void)viewDidLoad {
[super viewDidLoad];
// This Array Taken Globally
List_of_locationsArray =[[NSMutableArray alloc]initWithObjects:
#{#"latitude" : #"17.415045",#"logitude":#"78.421424"} ,#{#"latitude" : #"17.415045",#"logitude":#"78.421424"},#{#"latitude" : #"17.415045",#"logitude":#"78.421424"},#{#"latitude" : #"17.415045",#"logitude":#"78.421424"},#{#"latitude" : #"17.415045",#"logitude":#"78.421424"}
,nil];
}
-(void)sortingLocationsArray{
// CLLocation* currentLocation =[[CLLocation alloc]initWithLatitude:[currentLatitude doubleValue] longitude:[currentLogitude doubleValue]];
CLLocation* currentLocation =[[CLLocation alloc]initWithLatitude: currentLatitudeHere longitude:CurrentLogHere];
NSMutableArray* tempLocationsArr = [[NSMutableArray alloc]initWithCapacity:[locationsArray count]];
for (int i=0; i<[locationsArray count]; i++) {
CLLocationDegrees latValue = [[locationsArray[i] objectForKey:#"latitude"] doubleValue];
CLLocationDegrees longValue = [[locationsArray[i] objectForKey:#"logitude"] doubleValue];
CLLocation* location = [[CLLocation alloc]initWithLatitude:latValue longitude:longValue];
[tempLocationsArr addObject:location];
NSArray* sortLocationArry = [tempLocationsArr sortedArrayUsingComparator:^NSComparisonResult(CLLocation* location1, CLLocation* location2) {
CLLocationDistance distA = [location1 distanceFromLocation:currentLocation];
CLLocationDistance distB = [location2 distanceFromLocation:currentLocation];
if (distA < distB) {
return NSOrderedAscending;
} else if ( distA > distB) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}];
//ArrayAfterSorting is another mutable Array to Store Sorting Data
[ArrayAfterSorting removeAllObjects];
[sortLocationArry enumerateObjectsUsingBlock:^(CLLocation* location, NSUInteger idx, BOOL *stop) {
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc]init];
[tempDict setObject:[NSString stringWithFormat:#"%f",location.coordinate.latitude] forKey:#"latitude"];
[tempDict setObject:[NSString stringWithFormat:#"%f",location.coordinate.longitude] forKey:#"logitude"];
[ArrayAfterSorting addObject:tempDict];
}];
NSLog(#"sortedArray : %#", ArrayAfterSorting);
}
}
You may solve your problem in following way
1)Firstly store all above values in separate array Like latArray ,longArray,nameArray
2)Now get the distance between location(longArray,latArray) from your current location.
Then store these distances in separate Array(distanceArray).
//getDistance Between currentLocation and desired Location
-(void *)getDistanceFromCurrentLocation{
for(int val=0;val<[latArray count];val++){
NSString *dis_From_Current_Location;
dis_From_Current_Location =nil;
CGFloat str_Longitude=[[defaults objectForKey:#"long"]floatValue];
CGFloat str_Latitude=[[defaults objectForKey:#"lati"]floatValue];
//Suppose this is your current location
CGFloat lat1= [[latArray objectAtIndex:val]floatValue];
//these array for lat
CGFloat long1=[[longArray objectAtIndex:val]floatValue];
//these array for longArray
CLLocation *location1 = [[CLLocation alloc] initWithLatitude:lat1 longitude:long1];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:str_Latitude longitude:str_Longitude];
CLLocationDistance dist=[location1 distanceFromLocation:location2];
NSLog(#"Distance i meters: %f", [location1 distanceFromLocation:location2]);
long long v = llabs(dist/1000);
dis_From_Current_Location=[NSString stringWithFormat:#"%lld km",v];
[location1 release];
[location2 release];
[distanceArray addObject: dis_From_Current_Location];
//distanceArray is Global NsMutableArray.
}
}
Now You should Apply sorting method(selection, bubble) fro sorting the distances.
One thing need to care is that when you sort the distanceArray
please adjust values of nameArray as according to the distanceArray
See Below code for sorting the distanceArray and adjust the nameArray's value.
-(void)getSoretdArray{
NSString * tempStr,*tempStr2;
for(int i=0;i<[distanceArray count]; i++){
for(int j=i+1;j<[distanceArray count]; j++){
if([distanceArray objectAtIndex:j]>[distanceArray objectAtIndex:j+1]){
tempStr=[distanceArray objectAtIndex:j];
NSString* str= [distanceArray objectAtIndex:j+1];
[ distanceArray insertObject:str atIndex:j];
[distanceArray insertObject:tempStr atIndex:j+1] ;
//also change the name of corresponding location.
//you have to adjust the stored names in namArray for storing names of Corresponding Distances
tempStr2=[nameArray objectAtIndex:j];
NSString* str1= [nameArray objectAtIndex:j+1];
[ nameArray insertObject:str1 atIndex:j];
[nameArray insertObject:tempStr2 atIndex:j+1] ;
}
}
}
}
This will definitely work just try to use carefully