How to get a double value from an object posted with NSNotification - ios

I am having issues extracting a double from an NSObject.
I am receiving a notification like so
NSString *key = #"Post";
NSDictionary *dictionary = [notification userInfo];
Post* post = [dictionary objectForKey:key];
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = post.lat;
zoomLocation.longitude = post.lng;
NSLog(#"%f", post.lat);
NSLog(#"%#", post);
The NSLog for post.lat is nan. The NSLog for post is
(entity: Post; id: 0x85e9820 ; data: {
created = "2013-10-08 16:25:36 +0000";
lat = "-33.886336";
lng = "151.209565";
"post_id" = 2418;
})
Hopefully it is something really simple I am missing. Thanks in advance.
EDIT: When I try to use [post.lat doubleValue] it gets an error that prevents building "Bad receiver type 'double'"
ANSWER: I needed to extract the value like this
[[post valueForKey:#"lat"] doubleValue];

I see double quotes around the values of lat and png. That likely means that those values are really strings and not numbers.
If that is the case then you can use NSString#doubleValue to get a converted numeric value that is compatible with CLLocationCoordinate2D.latitude/longitude.

Maybe you can try it like this:
NSDictionary *location = #{#lat,#lng};
[[NSNotificationCenter defaultCenter] postNotificationName:#"NOTIFICATION" object:location];
Then get the location like this:
NSDictionary *location = notification.object;

depends on what class "lat" is. if it is an NSNumber then do [post.lat doubleValue]
Edit: from your updated question we see now that the Post.lat is indeed a double. However, as #St3fan pointed out the double quotes in the entity output make it appear as though that value is a string. So you have a double that is inited to NaN and is used for the property and another lat variable that is a string it would seem. Two separate variables.

Related

NSDictionary with float value return wrong conversion

I have NSDictionary with floating values, I am trying to get values like this
[[NSDictionary valueForKey:#"some_value"] floatValue];
but looks like value not rounded correctly.
For example:
I have value in dictionary: #"0.35" but after above conversion returns 0.34999999403953552 float value, #"0.15" converts into 0.15000000596046448 etc.
When you are converting value from string to float, it lost its precision so you have to format it again. Please look at below the question you will get the better idea of that.
Make a float only show two decimal places
Converting Dictionary value to float
NSString *str = [dict objectForKey:#"key"];
CGFloat strFloat = (CGFloat)[str floatValue];
Try this code, It will work for you. Tested!
float myFloatValue= 2345.678990;
NSString* formattedNumber = [NSString stringWithFormat:#"%.02f", myFloatValue];
NSLog(#"Changed Float Value:%#",formattedNumber);

What is the difference between #"1.5" and #(1.5) while setting the value in NSDictionary?

In iPhone project,
It was while I was while setting Value in dictionary,
NSMutableDictionary*dictionary=[[NSMutableDictionary alloc] init];
[dictionary setValue:#(2.8) forKey:#"Why"];
AND,
NSMutableDictionary*dictionary=[[NSMutableDictionary alloc] init];
[dictionary setValue:#"2.8" forKey:#"Why"];
My question is Why not #"2.5" and #(2.5) ?
You have two questions, it would be better to have a single question.
But as to the difference,#"2.5" is an NSString where #(2.5) is an NSNumber. There is a big difference between textual and numeric data.
As for why you need an NSNumber and not NSString is obvious: the kerning is a numeric value.
using the #() syntax you can box arbitrary C expressions. This makes it trivial to turn basic arithmetic calculations into NSNumber objects see below:
double x = 24.0;
NSNumber *result = #(x * .15);
NSLog(#"%.2f", [result doubleValue]);
You can also refer NSNumber object as #"" string but cant make calculations like above example. In your case both are acceptable but here calculation makes difference.
When you use
#"2.5" it's behave like a string
NSMutableDictionary*dictionary=[[NSMutableDictionary alloc] init];
[dictionary setValue:#"2.8" forKey:#"Why"];;
NSString *a = [dictionary ValueforKey:#"Why"];
but when you use #(2.8) then it's behave like a NSNumber
NSMutableDictionary*dictionary=[[NSMutableDictionary alloc] init];
[dictionary setValue:#(2.8) forKey:#"Why"];;
NSNumber *a = [dictionary ValueforKey:#"Why"];
#(2.8) is a type of NSNumber.
#"2.8" is a type of NSString.
Both the type and value were different between there two.

Attempting to drop pins based on MKMap from values from array

As the question says I am trying to add pins to my map based on the coordinates returned by my php file. Said file returns the following results
[{"dogid":"1","latitude":"15.435786","longitude":"-21.318447"},{"dogid":"1","latitude":"14.00000","longitude":"-18.536711"}]
What I am doing (well I believe i am) is taking the values from the link and saving them to a string. Secondly, save that string value to an array. Then, I go thru this array and save out the latitude and longitude and assign it to CLLocationCordinate 2dcoord. After whch I expect both pins to be dropped on whatever location they received.
However, what occurs is: Upon running the program, when it arrives on this lin
for (NSDictionary *row in locations) {
the loop is not run to assign the values, and it jumps to the end. Oddly, a single pin is dropped on the map (thou location doesnt appear to be the values that it waas passed).
Would appreciate a little incite into the matter.
Thanks
- (void)viewDidAppear:(BOOL)animated
{
NSMutableArray *annotations = [[NSMutableArray alloc] init];
NSURL *myURL =[NSURL URLWithString:#"link.php"];
NSError *error=nil;
NSString *str=[NSString stringWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:&error];
CLLocationCoordinate2D coord;
NSArray *locations=[NSArray arrayWithContentsOfFile:str];
for (NSDictionary *row in locations) {
NSNumber *latitude = [row objectForKey:#"latitude"];
NSNumber *longitude = [row objectForKey:#"longitude"];
// NSString *title = [row objectForKey:#"title"];
//Create coordinates from the latitude and longitude values
coord.latitude = latitude.doubleValue;
coord.longitude = longitude.doubleValue;
}
MKPointAnnotation *pin = [[MKPointAnnotation alloc] init];
pin.coordinate = coord;
[self.mapView addAnnotation:pin];
}
It looks like you are trying to save api response to and Array.
Api always returns json string which is NSString.
You need to convert decode json string.
In your case
NSString *str=[NSString stringWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:&error];
you need to decode str with [NSJSONSerialization JSONObjectWithData:<#(NSData )#> options:<#(NSJSONReadingOptions)#> error:<#(NSError *)#>] which give you proper array of dictionary.
Hope it will help you

subtracting latitudes with NSNumber type to find distance

I want to subtract two latitudes from each other to find the shortest distance, but I get this error, "Arithmetic on pointer to interface 'NSNumber', which is not a constant size in non-fragile ABI" If I change the - to a + I get a different error "Invalid operands to binary expression ('NSNumber *' and 'NSNumber *')" I've tried using doubles and many combinations of things, but it just doesn't work.
NSNumber *userLatitude = [NSNumber numberWithDouble:43.55];//sample
NSArray *listOfCities = [managedObjectContext executeFetchRequest:request error:&error];
for (CityList *item in listOfCities){
NSLog(#"latitude is %#",item.latitude);
NSNumber *distanceLat = userLatitude - item.latitude;
I will then insert them into a mutable array along with the longitudes and compare the distance. One possible solution using CLLocation would be
double distance = [usersCurrentLoc distanceFromLocation:otherLoc];
where usersCurrentLoc and otherLoc are both CLLocation variables.
I also want use the latitude and longitudes individually so I can do some custom plotting, and they are also stored separately, so I'd like to figure out the correct data types and most efficient solution.
item.latitude comes from core-data with the data model type of double and X-code auto generated the CityList class with a property of NSNumber * latitude;
If you want subtract two NSNumbers, then use this
NSNumber *distanceLat = [NSNumber numberWithFloat:([userLatitude floatValue] - [item.latitude floatValue])];
This:
NSNumber *distanceLat = userLatitude - item.latitude;
needs to be:
NSNumber *distanceLat = #([userLatitude doubleValue] - item.latitude);
If item.latitude is also an NSNumber then you need to call doubleValue on it too.
NSNumber is an object. You can't do math on the object. You need to use doubleValue to get its value and then you need to wrap the result in a new NSNumber instance.
BTW - why bother with NSNumber here? Why not do:
double userLatitude = 43.55;
double distanceLat = userLatitude - item.latitude;
CLLocationCoordinate2D newCoordinate = [newLocation coordinate];
CLLocationCoordinate2D oldCoordinate = [oldLocation coordinate];
CLLocationDistance meters = [newLocation distanceFromLocation:oldLocation];
The above one can be used to find distance between two locations

How to implement %0.7f in annotation.coordinate?

I have two strings which hold values say for ex:35.5044752 97.3955550
Let me convert it :
double f1=[la doubleValue];
double f2=[lo doubleValue];
(value of f1 and f2 is dynamic say for example f1= "35.5044752" f2="97.3955550" )
if i want to print it in NSLog i will do as follows :
NSLog(#" %f %f ",f1,f2);
And it returns 35.504475 97.395555
hence i change it as
NSLog(#" %0.7f %0.7f ",f1,f2);
And gets the full values like 35.5044752 97.3955550
Now i need it to use in the Coordinate like below:
annotation.coordinate=CLLocationCoordinate2DMake(coord.longitude, coord.longitude);
My Question is how can i implement %0.7f here like which i made in NSlog ?
so that i should take input fully instead of reducing or altering the value.
make a try like this. Directly pass values to obj center
CLLocationCoordinate2D center;
...
else if ([elementName isEqualToString:#"Lat"]) {
center.latitude = [[attributeDict objectForKey:#"degrees"] doubleValue];
}
else if ([elementName isEqualToString:#"Lon"]) {
center.longitude = [[attributeDict objectForKey:#"degrees"] doubleValue];
}
...
OR
Archived the coordinate in foundLocation:
NSNumber *latitudeObject = [NSNumber numberWithDouble:coord.latitude];
NSNumber *longitudeObject = [NSNumber numberWithDouble:coord.longitude];
NSArray *coordinateArray = [NSArray arrayWithObjects:latitudeObject, longitudeObject, nil];
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:coordinateArray]
forKey:WhereamiCoordinatePrefKey];
Unarchived the coordinate in viewDidLoad:
NSArray *coordinateArray = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults]
objectForKey:WhereamiCoordinatePrefKey]];
CLLocationCoordinate2D savedCoordinate = CLLocationCoordinate2DMake([[coordinateArray objectAtIndex:0] doubleValue],
[[coordinateArray objectAtIndex:1] doubleValue]);
MKCoordinateRegion savedRegion = MKCoordinateRegionMakeWithDistance(savedCoordinate, 250, 250);
[worldView setRegion:savedRegion animated:YES];
The %0.7f format specifier deals with how your value is displayed, not with how it is stored. A double is always double and has its inherent precision and nothing you can do, short of casting it to another data type, will change that.
As far as I know, the double data type offers the highest floating point precision of the standard data types. If you need greater precision than that, you're going to have to use something other than a double.
In other words, when you perform an operation on a double, it is always calculated to the full precision allowed by the double data type.
For more information on the subject, see the Wikipedia entry on floating point data types.

Resources