I am trying to create Price class that extends NSDecimalNumber but when trying to alloc it and init it is raising exceptions. Any idea what can be a problem?

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Did you forget to nest alloc and initWithString: ?'

Price.h

#import <Foundation/Foundation.h>

@interface Price : NSDecimalNumber
+ (Price*)priceWithString:(NSString*)val;
@end

Price.m

#import "Price.h"

@implementation Price
- (NSString *)description {
    return [[super description] stringByAppendingString:@" €"];
}
+ (Price*)priceWithString:(NSString*)val {
    return [[Price alloc] initWithString:val];
}
@end

Edit: Even bare class is not working. If I am extending NSDecimalNumber and then trying to do alloc init, the same exception. I gave up at this...

有帮助吗?

解决方案

NSDecimalNumber inherits NSNumber, which is a class cluster. This makes it very tough to inherit NSDecimalNumber, because there is a number of additional requirements for such inheriting. According to Apple documentation, your class needs to

  • Be a subclass of the cluster’s abstract superclass
  • Declare its own storage
  • Override all initializer methods of the superclass
  • Override the superclass’s primitive methods (described below)

In your case, your Price class would need to re-implement a lot of NSDecimalNumber, which is probably too much work.

A better approach would be to nest NSDecimalNumber inside your Price class, and add a method to obtain its numeric value, like this:

@interface Price : NSObject

/// Represents the numeric value of the price
@property (nonatomic, readonly) NSDecimalNumber *valueInLocalCurrency;

/// Represents the pricing currency
@property (nonatomic, readonly) NSString *currencyCode;

/// Creates an immutable Price object
-(id)initWithPriceInLocalCurrency:(NSDecimalNumber*)price andCurrencyCode:(NSString*)currencyCode;

@end

Once consequence of this decision is that you can no longer send a Price object to places where an NSDecimalNumber object is expected. This has a potential of preventing silly errors when you disregard the currency by mistake, so it is probably a good safety measure.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top