Question

Hi for starters let me say thank you for helping me out on this problem. I'm currently trying to learn Objective-C. I first started learning Java in AP Computer Science (taught at my High School) games... however, I've been trying to expand from Java into Objective-C. Mostly so I can mess around making iPhone apps. I've read quite a few guides but I keep getting stuck and overwhelmed so I just stop what I'm doing and head back to java.. However, this time I'm determined to get past this little problem! All responses are appreciated! So here is my VectorObject class that I will be using in my Sprite 2-D game Test Project. However, I'm having trouble with just general Objective-C syntax. I've tried several different things but can't seem to make it work, I just get errors.

TLDR: Here are my classes, I'm trying to make a VectorObject with the desired instance variables but I don't know how to properly add the parameter to the instance variable.

#import <Foundation/Foundation.h>

@interface VectorObject : NSObject

@property(nonatomic) BOOL alive;
@property(nonatomic) NSDecimal *x;
@property(nonatomic) NSDecimal *y;
@property(nonatomic) NSDecimal *velX;
@property(nonatomic) NSDecimal *velY;
@property(nonatomic) NSDecimal *maxVelX;
@property(nonatomic) NSDecimal *maxVelY;
@property(nonatomic) NSDecimal *moveAngle;
@property(nonatomic) NSNumber *faceAngle;

- (void)incX:(NSDecimal *) x;
- (void)incY:(NSDecimal *) y;
- (void)incVelY:(NSDecimal *) velY;
- (void)incVelX:(NSDecimal *) velX;
- (void)incFaceAngle:(NSDecimal *) faceAngle;
- (void)incMoveAngle:(NSDecimal *) moveAngle;
+ (NSDecimal)calcAngleMoveX:(NSDecimal *) ang;
+ (NSDecimal)calcAngleMoveY:(NSDecimal *) ang;

@end

And now for my implementation class.

#import "VectorObject.h"

@implementation VectorObject

@synthesize alive;
@synthesize x, y;
@synthesize velX, velY;
@synthesize maxVelX, maxVelY;
@synthesize moveAngle, faceAngle;

-(void)incY:(NSDecimal *)y
{

}
-(void)incX:(NSDecimal *)x
{

}
-(void)incVelY:(NSDecimal *)velY
{

}
-(void)incVelX:(NSDecimal *)velX
{

}
-(void)incFaceAngle:(NSDecimal *)faceAngle
{

}
-(void)incMoveAngle:(NSDecimal *)moveAngle
{

}
+(NSDecimal) calcAngleMoveX:(NSDecimal *)ang
{

}
+(NSDecimal) calcAngleMoveY:(NSDecimal *)ang
{

}

@end

So I know in Java I could simply define the incX(double x) like so

public void incX(double x)
{
    this.x += x;
}

But I'm not sure how I would do this in Objective-C?

-(void)incX:(NSDecimal *)x
{
     self.x += [NSDecimal *] x;
}

Edit: All syntax tips, general implementation, etc are appreciated and will be put to use!

Was it helpful?

Solution

In Java you have used double - this is a primitive value type, its not an object. Standard math operations can be used with double

In Objective-C you have used NSDecimal *- this is a pointer to a value type, it's also not an object but maybe you intended to use NSDecimalNUmber * which is. You must you the functions (NSDecimal) or methods (NSDecimalNumber) provided by the types, you cannot use standard math operations.

Why not just use double in Objective-C, it is a standard primitive value type. There is also float with lower precision.

OTHER TIPS

self.x += [NSDecimal *] x;

No, that's not quite right. Do this instead:

self.x = [self.x decimalNumberByAdding:x];

When working with NSDecimalNumber, look at the class reference to see what methods you can use and remember that NSDecimalNumber objects are immutable, so operations on them return new objects.

A minor point: it might be a little less confusing if you use a different name for the number that you're adding, like:

-(void)incX:(NSDecimalNumber *)increment
{
     self.x = [self.x decimalNumberByAdding:increment];
}

One thing you need to know is that iOS and OS X wrap the base types and provide functions to help you use them. They've done this b/c the wrappers gave a abstraction away from hardware and chip dependencies on size, etc. for base types like float and double. So hopefully this helps you understand your options for using numbers on iOS and OS X in Objective-C.

NSDecimal structs are a 'Foundation' type in iOS and OS X Objective-C. They are 'C' structs. The links below to the docs go into more detail. There is also a class NSDecimalNumber that you can use from your Objective-C code. It's methods will take NSDecimals as arguments. You can use either NSDecimal or NSDecimalNumber. Use NSDecimal if want to work at the 'C' function/procedural level. Use NSDecimalNumber if you want to work with objects and at the Objective-C message syntax level. Note that you can also use both levels as well.

Here are links to Apples documentation for them right below before I put an answer as well.

Very Important Docs for using Numbers on iOS and OS X

Intro to Numbers and Other Values

https://developer.apple.com/library/mac/documentation/cocoa/Conceptual/NumbersandValues/NumbersandValues.html#//apple_ref/doc/uid/10000038i

The section 'Using Decimal Numbers' is the main one you'll care about, but since

Structs

NSDecimal

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_DataTypes/Reference/reference.html

Functions to do math with NSDecimal structs here.

Foundation Functions

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/doc/uid/20000055-BCIHCEFJ

Objects

NSDecimalNumber

https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/classes/nsdecimalnumber_class/reference/reference.html


Solution Without Changing Your Class

Your class defines the properties as NSDecimal and you pass in a NSDecimal arg. So you can solve it two basic ways. One by using the 'C' level 'Foundation' functions such as NSDecimalAdd and the other by using the class NSDecimalNumber. The second one is what I'm going to show.

The code for your incX: method would look like:

// I changed your method name to make it 
// more like other Objective-C code that read more like a sentence
// I changed the argument name because your really adding the new value to x
-(void)incrementXBy:(NSDecimal*)incrementValue
{
  // _x is what the @property annotation creates for us for the property x

  // Create a NSDecimalNumber object from our internal NSDecimal struct in _x
  NSDecimalNumber currentXAsDN = [NSDecimalNumber decimalNumberWithDecimal: _x];

  // Create a NSDecimalNumber object from the argument NSDecimal passed to us
  NSDecimalNumber incrementValueAsDN = [NSDecimalNumber decimalNumberWithDecimal: incrementValue];

  // Now we can add the two objects 
  NSDecimalNumber newX = [currentXAsDN decimalNumberByAdding: incrementValueAsDN];

  // Since we have our property 'x' defined as a NSDecimal, get that struct out of our newX object and set our 'x' property to it.
  _x = [newX decimalValue];

}

That is a solution based on how you have your class declared.

To do it without creating the NSDecimalNumber objects use the function NSDecimalAdd that works directly on NSDecimal structs. To do that you need to decide how you the RoundingMode and such detailed in the function docs for NSDecimalAdd(). I'm guessing your wanting to stay with NSDecimal because it's a struct and you need performance, but if it isn't that big a deal you can change your properties to use NSDecimalNumber objects. That would simplify the code example up above by making it so that you didn't need to create the NSDecimalNumber objects from the NSDecimal structs.

Another approach to this problem is to declare your properties using 'C' doubles. If you do that your code will look like normal 'C' code. But be very aware if you do that you are trading off the frameworks wrapping and the reasons behind it.

Better Solution IMHO

I'd change your class to have the properties use NSDecimalNumber and also pass in a instance of NSDecimalNumber to your methods. If you do so then the method would look like this:

-(void)incrementXBy:(NSDecimalNumber*)incrementValue
{

  // Now we can add the two objects 
  _x = [currentXAsDN decimalNumberByAdding: incrementValueAsDN];

}

Which is much cleaner I think.

Hope that helped.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top