Pass-by-value argument in message expression is undefined - iphone

I'm developing an iPhone application and I getting that warning at method:
NSNumber *latitudeValue;
NSNumber *longitudeValue;
[self obtainLatitude:latitudeValue longitude:longitudeValue];
The method is declared as follows:
- (void) obtainLatitude:(NSNumber *)latitudeValue longitude:(NSNumber *)longitudeValue {
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
latitudeValue = [f numberFromString:[latitude.text stringByReplacingOccurrencesOfString:#"," withString:#"."]];
longitudeValue = [f numberFromString:[longitude.text stringByReplacingOccurrencesOfString:#"," withString:#"."]];
[f release];
}
As you can see, I'm trying to calculate latitudeValue and longitudeValue calling obtainLatitude:longitude: but I'm doing something wrong.
How can I fix that error?

Elfred's answer works, but pass-by-reference for non-NSError** parameters is pretty uncommon. As well, coordinates -- numeric values, in general -- are most typically stored in regular old C types in structures because, comparatively, an NSNumber is quite a bit of overhead (no big deal for a few of 'em, would be a problem if you have a few dozen, hundred, or thousands of coordinates).
Something like:
struct MyLocation {
CGFloat latitude;
CGFloat longitude;
};
typedef struct MyLocation MyLocation;
Then:
- (MyLocation) mapCoordinates {
MyLocation parsedLocation;
parsedLocation.latitude = ....;
parsedLocation.longitude = ....;
return parsedLocation;
}
Something like the above would be more typical in an iPhone/Cocoa program.
As Dave points out, you really don't need to define your own type for this. Use CLLocationCoordinate2D or CLLocation.

You are indeed passing the pointers by value, so when you reassign them, that just takes effect inside thee method. One alternative is to do the following:
- (void) obtainLatitude:(NSNumber **)latitudeValue longitude:(NSNumber **)longitudeValue {
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
*latitudeValue = [f numberFromString:[latitude.text stringByReplacingOccurrencesOfString:#"," withString:#"."]];
*longitudeValue = [f numberFromString:[longitude.text stringByReplacingOccurrencesOfString:#"," withString:#"."]];
[f release];
}
then your call would look like:
NSNumber *latitudeValue;
NSNumber *longitudeValue;
[self obtainLatitude:&latitudeValue longitude:&longitudeValue];

Related

Elegant method to omit fraction formatting number if number is an integer

I am formatting floating point numbers and right now I have the %0.2f formatter, but I'd like to omit the .00 if the floating point number is an even integer.
Of course I can think of string replacing the .00, but that's crude.
I found that the description of NSNumber also does something similar:
NSNumber *number = [NSNumber numberWithFloat:_paragraphSpacing];
[retString appendFormat:#"margin-bottom:%#px;", number];
This this does hover not limit the post comma digits. if the number is 1234.56789 then the description will output that.
So my question is, is there a just as simple way - possibly without having to create an NSNumber object - to achieve this result?
Since floating-point numbers aren't exact, there's no guarantee that your number will actually be an integer. You can, however, check if it's within a reasonably small distance from an integer value. And of course you don't need an NSNumber for this. (Generally speaking, NSNumber is not used for formatting, its purpose is representing a primitive C type, either integral or floating-point types, using an Objective-C object.)
#include <math.h>
- (NSString *)stringFromFloat:(float)f
{
const float eps = 1.0e-6;
if (abs(round(f) - f) < eps) {
// assume an integer
return [NSString stringWithFormat:#"margin-bottom: %.0fpx", round(f)];
} else {
// assume a real number
return [NSString stringWithFormat:#"margin-bottom: %.2fpx", f];
}
}
Use a formatter:
NSNumberFormatter* formatter= [NSNumberFormatter new];
formatter.numberStyle= NSNumberFormatterDecimalStyle;
formatter.maximumFractionDigits=2;
NSNumber *number = [NSNumber numberWithFloat:_paragraphSpacing];
[retString appendFormat:#"margin-bottom:%#;", [formatter stringFromNumber: number]];
You can use an NSNumberFormatter for this:
static NSNumberFormatter *numberFormatter = nil;
if (numberFormatter == nil) {
numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.minimumFractionDigits = 0;
numberFormatter.maximumFractionDigits = 2;
numberFormatter.usesGroupingSeparator = NO;
}
NSString *formattedNumberString = [numberFormatter
stringForNumber:[NSNumber numberWithDouble: _paragraphSpacing]];
You can use C function modff to get the fraction part and test it:
float fractionPart = 0.;
modff(_paragraphSpacing, &fractionPart);
if( fabsf(fractionPart) < 0.01 ) {
// format as integer
[retString appendFormat:#"margin-bottom:%d", (int)_paragraphSpacing];
} else {
// format as float
[retString appendFormat:#"margin-bottom:%0.2f", _paragraphSpacing];
}

Divide int and return a float

I have a problem that I can not fix with a number, I'll explain.
At one point in my code I call a function that returns an int, then I divide it and have a float with two decimal places.
My Ex 69033792 Fuzion back, I want to have to divide by 1024 and 67415.81
I write
NSInteger mem_0 = [self printMemoryInfo:#"0"];
[self.mem1 setText:[NSString stringWithFormat:#"%.2f",(mem_0/1024f)]];
but I do not return the decimal part ... What's wrong?
thanks
myDouble = [[NSNumberFormatter alloc] init];
[myDouble setFormatterBehavior:NSNumberFormatterBehavior10_4];
[myDouble setNumberStyle:NSNumberFormatterDecimalStyle];
[myDouble setRoundingMode:NSNumberFormatterRoundHalfUp];
[myDouble setMinimumFractionDigits:0];
[myDouble setMaximumFractionDigits:2];
NSInteger mem_0 = [self printMemoryInfo:#"0"];
[self.mem1 setText:[myDouble stringFromNumber:[NSNumber numberWithDouble: mem_0/1024]]];
[myDouble release];
You should be getting the compile-time error "Invalid digit 'f' in decimal constant", because 1024f is not legal. You need to say it like this:
[self.mem1 setText:[NSString stringWithFormat:#"%.2f",(mem_0/1024.0f)]];
or you can just say 1024.0 without the f, because it will be passed to stringWithFormat: as a double anyway.

Correctly convert NSString to NSnumber

I can't figure out why it's not working, I have a NSString which I need to convert to NSNumber (to save it to Core Data)
e.g
NSLog(stringNum);
returns 1
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *myNumber = [f numberFromString:stringNum];
[f release];
NSLog(#"myNumber = %i", myNumber);
returns 120882496 or something like this
What am I missing?
Thanks for help
It's now an object, not an integer, therefore you must use %# in NSLog, not %i.
myNumber is an object, so the format should be
#"myNumber = %#"

How do I convert the value of a UITextField to an NSNumber?

I have a small problem with iPhone SDK. I have 4 values in my xib, 4 UITextFields where I insert hostname, description, name and PORT.
The Port is an NSNumber. I must convert text (UITextField) into NSNumber but I don't know how.
I tried the following:
NSNumber *temp = [[NSNumber alloc] initWithString:portTextField.text];
serverObj.port = temp;
but my app crashes. I don't have problems with NSString (description ecc.)
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * myNumber = [f numberFromString:textField.text];
[f release];
And that should get the job done.
Just use the 'integerValue' method of NSString, to get a 'NSInteger'. Then you can create a NSNumber object from it.
serverObj.port = [ NSNumber numberWithInteger: [ portTextField.text integerValue ] ];
There is no method for NSNumber objects called initWithString: (that's why your app crashes). You need to use NSNumberFormatter's method numberFromString:

How can I have tick marks in Core Plot with custom labels?

For my app's graph (line plots) it does not make sense to format the axis labels to tenths. It did not look like there was a way to change this without providing custom labels.
I was able to add custom axis labels based on the sample code in this answer, but the labels do not have tick marks.
Is this an issue (I didn't see anything here) or am I missing something?
If you want numeric labels with a format different than the default, create an NSNumberFormatter object, set it to whatever format you need, and assign it to the labelFormatter property on the axis.
Check out the CPTimeFormatter class if you need to format the labels as dates and/or times.
Derive a class from NSNumberFormatter (e.g. MyFormatter) and override stringForObjectValue:
- (NSString *)stringForObjectValue:(NSDecimalNumber *)coordinateValue {
return #"MyLabel";
}
Then set the labelFormatter property of your axis to an instance of MyFormatter, e.g.:
MyFormatter *formatter = [[MyFormatter alloc] init];
x.labelFormatter = formatter;
[formatter release];
This worked for me!
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setMaximumFractionDigits:0];
y.labelFormatter = formatter;
You can also swizzle the method in category like this:
#import "NSNumberFormatter+BigNumber.h"
#import <objc/runtime.h>
static Method origStringFromNumberMethod = nil;
#implementation NSNumberFormatter (BigNumber)
-(NSString *)stringFromBigNumber:(NSNumber*)number{
int result = 0;
int level = 1;
NSString *format = #"";
if([number integerValue] >= 1000000000) {
level = 1000000000;
format = #"b";
}
if([number integerValue] >= 1000000) {
level = 1000000;
format = #"m";
}
if([number integerValue] >= 1000){
level = 1000;
format = #"k";
}
result = [number integerValue]/level;
NSString *kValue = [NSString stringWithFormat:#"%d%#",result,format];
return kValue;
}
+ (void)initialize {
origStringFromNumberMethod = class_getClassMethod(self, #selector(stringFromNumber:));
method_exchangeImplementations(origStringFromNumberMethod,
class_getClassMethod(self, #selector(stringFromBigNumber:)));
}
#end