cannot call function from other function - objective-c

I need to get abs. the value of NSDecimalNumber. And I use pre-defined function for that:
- (NSDecimalNumber *)aDN: (NSDecimalNumber *)num {
if ([num compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
// negative value
return [[NSDecimalNumber zero] decimalNumberBySubtracting:num];
} else {
return num;
}
}
However when I try to call it from other function. Namely
- (void) prepareForSeque....
wordD=aDN(number);
I get the error: " Implicit declaration of function 'aDN' is invalid in C99'
Can you give me some pointers how to troubleshoot this?
Thanks in advance.

You appear to be confusing languages. It looks like you should have
wordD = [self aDN:number];
(Assuming the class hosting the method is the current class and not a category on decimal number which might make more sense...)

Related

Writing a function that accepts NSString and floats

I'm trying to do an iPad application.
In one of the functions, I'm supposed to return a value depending on the string input.
Here's the code:
float myFunction(float t, NSString * Color){
if ([Color isEqual:#"blue"])
return t*100;
else if ([Color isEqual:#"red"])
return t*2;
else
return t;
}
But somewhere my program does something wrong. Since I don't get the number I'm expecting. Is it possible that this code is the missing link?
I get no errors or warnings.
instead of isEqual you should use isEqualToString
and change Color to color
Try if this makes a difference (if not the problem lies elswhere in the code):
float myFunction(float t, NSString * color){
if ([color isEqualToString:#"blue"])
return t*100.0;
else if ([color isEqualToString:#"red"])
return t*2.0;
else
return t;
}
If you want your function to look more like obj-c method then use:
-(CGFloat) myFunctionForT:(CGFloat)t andColor:(NSString *)color {
if ([color isEqualToString:#"blue"])
return t*100.0;
else if ([color isEqualToString:#"red"])
return t*2.0;
else
return t;
}
The main reason for using color instead of Color and 100.0 instead of 100 is that a bit more discipline in coding saves you hours and hours of debugging time.

correct way to send messages to (id *) variables or with (id *) arguments

I have a Core Data validation method I wrote that will not compile. I can modify the method so it compiles... but then I get runtime errors. The two versions of the method are below (notice the missing '*' in the second version). This version compiles but gives the runtime error "+[NSCFNumber doubleValue]: unrecognized selector sent to class 0x7fff70a448e8":
- (BOOL)validateInitialValue:(id *)value error:(NSError **)error {
if ( *value == nil ) {
return YES;
}
if ( [*value doubleValue] < 0.0 ) {
return NO;
}
return YES;
}
This version gives compiler warnings and errors (see warnings and errors below):
- (BOOL)validateInitialValue:(id *)value error:(NSError **)error {
if ( value == nil ) {
return YES;
}
if ( [value doubleValue] < 0.0 ) {
return NO;
}
return YES;
}
compiler errors and warnings:
warning: Semantic Issue: Receiver type 'id *' is not 'id' or interface pointer, consider casting it to 'id'
warning: Semantic Issue: Method '-doubleValue' not found (return type defaults to 'id')
error: Semantic Issue: Invalid operands to binary expression ('id' and 'double')
I finally figured that the problem may be in the calling code:
- (void)setInitialValue:(NSNumber *)initialValue {
[self willChangeValueForKey:#"initialValue"];
[self validateValue:initialValue forKey:#"initialValue" error:nil];
[self setPrimitiveInitialValue:initialValue];
[self didChangeValueForKey:#"initialValue"];
}
I changed the caller to use an '&' before initialValue and used the first version of the method, and everything worked. So the new calling code has the one line changed to be this:
[self validateValue:&initialValue forKey:#"initialValue" error:nil];
But is it really necessary to have the '&'?? setPrimitiveInitialValue doesn't use the '&'. I feel like my understanding of Objective-C is just not developed enough yet and all you gurus out there will find this a trivial question with a very straight forward answer.
id itself represents a pointer. So when you use id * you are actually referring to a pointer-to-a-pointer. The first part of this excellent tutorial explains this concept.
Chances are, this is what you are looking for:
- (BOOL)validateInitialValue:(id)value error:(NSError **)error {
if ( value == nil ) {
return YES;
}
if ( [value doubleValue] < 0.0 ) {
return NO;
}
return YES;
}
You're right that the problem is the calling code. id * indicates a pointer to an id value. An object variable by itself is an id, so you want a pointer to that variable, which is what you get with the &.
The reason you pass a pointer is so that, if your validation method knows of a way to modify the value to make it valid, it can return YES and also return the valid object (by setting the variable). So, for example, if numbers less than 1 should be clamped to 0, you might do:
- (BOOL)validateInitialValue:(id *)value error:(NSError **)error {
if ( *value == nil ) {
return YES;
}
if ( [*value doubleValue] < 0.0 ) {
return NO;
}
if ( [*value doubleValue] > 0.0 && [*value doubleValue] < 1.0 ) {
*value = [NSNumber numberWithInt:0];
}
return YES;
}
setPrimitiveValue: doesn't need to set variables in the calling context, so it just takes an id. (Very few methods work like validateValue:forKey:error:. Generally, they'll do it that way if they want to return a BOOL to indicate whether they changed something, but they still need a way to return the changed value as well.)

convert id into enum using objective-c

I am trying to implement a simple method, however I am still quite a newbie on objective-c.
I have this simple method which is trying to convert from an id to a specific value in enum, if matched.
This is the enum
typedef enum {
DXTypeUnknown = 0,
DXDatasource = 1,
DXGroup = 2
} DXPropertyType;
And this is the relevant method:
-(DXPropertyType)typeFromObject:(id)_type {
int _t = [_type intValue];
switch (_t) {
case DXDatasource:
return [NSNumber numberWithInt:DXDatasource];
case DXGroup:
return [NSNumber numberWithInt:DXGroup];
default:
return [NSNumber numberWithInt:DXTypeUnknown];
}
}
The very first check I would to implement is if the id can be converted to an int, then see if it falls in the two relevant categories group or datasource, or return a default value if not. Could you tell me if the switch/case I implemented is a proper solution or not ?
I would like also this method not to causing crash of an application, so what could be advisable to check, keeping in mind that in any case the default value is to be returned.
thanks
[EDIT]
I forgot to say that this value is going to be stored in a field of a NSManagedObject, which by CoreData restriction can be an NSNumber, so probably there's a better solution instead of an enum.
It might be a good idea to include this code to check if the id can be used:
if (![_type respondsToSelector:#selector(intValue)])
return nil;
However, if you'll always pass a NSNumber go ahead and declare the method as:
- (DXPropertyType)typeFromObject:(NSNumber)_type;
In your code, you're returning a NSNumber. I don't think that's what you really
want, as you'd be doing nothing with the NSNumber passed. Return the enum
item:
-(DXPropertyType)typeFromObject:(id)_type {
if (![_type respondsToSelector:#selector(intValue)])
return nil;
int _t = [_type intValue];
switch (_t) {
case DXDatasource:
return DXDatasource;
case DXGroup:
return DXGroup;
default:
return DXTypeUnknown;
}
}
And then this can be simplified to:
- (DXPropertyType)typeFromObject:(id)_type {
if ([_type respondsToSelector:#selector(intValue)]) {
int t = [_type intValue];
DXPropertyType property_t;
if (t >= 1 && t <= 2)
property_t = t;
else
property_t = DXTypeUnknown;
return property_t;
}
return nil;
}
Your switch statement is a good solution and will not cause a crash.
However, your method returns a NSNumber when it expects a different return. I suggest changing the method to
-(NSNumber)typeFromObject:(id)_type
You specify that your method returns an enum, but you return objects. So either return the enum values or specify the return type to be NSNumber *.
A different solution could be using singleton objects instead of an enum, but that's probably more work than it's worth. Think [NSNull null].

pointer before declaration of object objective-c

can you tell me something : is it a mistake or can we write "result" without the " * " here :
#implementation Person (Sorting)
- (NSComparisonResult)compareByName:(Person *)person2 {
>>//here :
>>NSComparisonResult result = [self.lastName caseInsensitiveCompare:person2.lastName];
if (result == NSOrderedSame) {
return [self.firstName caseInsensitiveCompare:person2.firstName];
}
return result;
}
#end
Thanks
caseInsensitiveCompare method returns NSComparisonResult so not using * is absolutely correct.
In objective-c you must use pointers to obj-c objects, but NSComparisonResult is just an enum (i.e. plain integer) so you may freely use it without pointer.

Objective C Function Question

Hey guys, check this out. I have a function that treats for me a string. No matter what it does, i just want to knwo if is possible to this function return the result for the place that it was executed. I mean, check this:
[self priceFormat:#"1"];
priceLabel.text = price;
-(void) priceFormat:(NSString*)price {
price = #"2";
}
I just want to my function treats the string and return it to the same place that it was executed.
Thanks!
Three ways to do this
Way one, using a pointer
- (void)priceFormat:(NSString **)price {
*price = #"2";
}
Wat two, using an instance variable
What you might want instead is an ivar. In the interface (most often the h file) of your class:
NSString *price;
and in the implementation (the m or mm file):
- (void)priceFormat:(NSString *)price {
price = #"2";
}
I have created an example of this here.
If you want the price to be available to other objects as well (not just self), you might want to create a property for it and synthesize it. Then use self.price = #"2"; instead. More on this here: http://MacDeveloperTips.com/objective-c/objective-c-properties-setters-and-dot-syntax.html
Just make sure you make it a copy property (NSString in use)!
Way three using return
Note, that you can also return directly from a method:
- (NSString *)priceFormat:(NSString *)price {
return #"2";
}
priceLabel.text = [self priceFormat:#"1"];