Subclassing NSNumber is a bit of work but it is doable. However You would need to rewrite most of the methods.
If you want to create your on NSMutableNumber for whatever reason, and in order for you class to work properly, you would have to override most of the methods except a few; Keep in mind that changing a value of any type will result in changing all the others, and will update the objCType
property, so you would want to override your setters accordingly as well. I have written such a subclass that is mutable and behaves mostly like an NSNumber with a few different details and extra methods; The description
for a BOOL
type now returns a YES
or NO
string instead of 1
or 0
, also I have added initWithDecimal
, numberWithDecimal
, initWithLongDouble
and numberWithLongDouble
methods as well.
here it goes:
Here is your NSMutableNumber.h
file:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSMutableNumber : NSNumber
@property(nonatomic, readwrite) BOOL boolValue;
@property(nonatomic, readwrite) char charValue;
@property(nonatomic, readwrite) unsigned char unsignedCharValue;
@property(nonatomic, readwrite) short shortValue;
@property(nonatomic, readwrite) unsigned short unsignedShortValue;
@property(nonatomic, readwrite) int intValue;
@property(nonatomic, readwrite) unsigned int unsignedIntValue;
@property(nonatomic, readwrite) NSInteger integerValue;
@property(nonatomic, readwrite) NSUInteger unsignedIntegerValue;
@property(nonatomic, readwrite) long longValue;
@property(nonatomic, readwrite) unsigned long unsignedLongValue;
@property(nonatomic, readwrite) long long longLongValue;
@property(nonatomic, readwrite) unsigned long long unsignedLongLongValue;
@property(nonatomic, readwrite) float floatValue;
@property(nonatomic, readwrite) double doubleValue;
@property(nonatomic, readwrite) long double longDoubleValue;
@property(nonatomic, readwrite) NSDecimal decimalValue;
@property(nonatomic, readwrite) const char *objCType;
+ (NSMutableNumber *)numberWithBool:(BOOL)value;
+ (NSMutableNumber *)numberWithChar:(char)value;
+ (NSMutableNumber *)numberWithUnsignedChar:(unsigned char)value;
+ (NSMutableNumber *)numberWithShort:(short)value;
+ (NSMutableNumber *)numberWithUnsignedShort:(unsigned short)value;
+ (NSMutableNumber *)numberWithInt:(int)value;
+ (NSMutableNumber *)numberWithUnsignedInt:(unsigned int)value;
+ (NSMutableNumber *)numberWithInteger:(NSInteger)value;
+ (NSMutableNumber *)numberWithUnsignedInteger:(NSUInteger)value;
+ (NSMutableNumber *)numberWithLong:(long)value;
+ (NSMutableNumber *)numberWithUnsignedLong:(unsigned long)value;
+ (NSMutableNumber *)numberWithLongLong:(long long)value;
+ (NSMutableNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
+ (NSMutableNumber *)numberWithFloat:(float)value;
+ (NSMutableNumber *)numberWithDouble:(double)value;
+ (NSMutableNumber *)numberWithLongDouble:(long double)value;
+ (NSMutableNumber *)numberWithDecimal:(NSDecimal)value;
- (NSMutableNumber *)initWithBool:(BOOL)value;
- (NSMutableNumber *)initWithChar:(char)value;
- (NSMutableNumber *)initWithUnsignedChar:(unsigned char)value;
- (NSMutableNumber *)initWithShort:(short)value;
- (NSMutableNumber *)initWithUnsignedShort:(unsigned short)value;
- (NSMutableNumber *)initWithInt:(int)value;
- (NSMutableNumber *)initWithUnsignedInt:(unsigned int)value;
- (NSMutableNumber *)initWithInteger:(NSInteger)value;
- (NSMutableNumber *)initWithUnsignedInteger:(NSUInteger)value;
- (NSMutableNumber *)initWithLong:(long)value;
- (NSMutableNumber *)initWithUnsignedLong:(unsigned long)value;
- (NSMutableNumber *)initWithLongLong:(long long)value;
- (NSMutableNumber *)initWithUnsignedLongLong:(unsigned long long)value;
- (NSMutableNumber *)initWithFloat:(float)value;
- (NSMutableNumber *)initWithDouble:(double)value;
- (NSMutableNumber *)initWithLongDouble:(long double)value;
- (NSMutableNumber *)initWithDecimal:(NSDecimal)value;
- (NSString *)stringValue;
- (NSString *)description;
- (NSString *)descriptionWithLocale:(NSLocale *)locale;
@end
NS_ASSUME_NONNULL_END
Here is your NSMutableNumber.m
file:
#import "NSMutableNumber.h"
@interface NSMutableNumber ()
- (void)setAllIntValues:(unsigned long long)ULLongVal allFloats:(long double)LDoubleVal;
- (NSMutableNumber *)initAllints:(unsigned long long)ULLongVal allFloats:(long double)LDoubleVal;
@end
@implementation NSMutableNumber
@synthesize boolValue;
@synthesize charValue;
@synthesize unsignedCharValue;
@synthesize shortValue;
@synthesize unsignedShortValue;
@synthesize intValue;
@synthesize unsignedIntValue;
@synthesize integerValue;
@synthesize unsignedIntegerValue;
@synthesize longValue;
@synthesize unsignedLongValue;
@synthesize longLongValue;
@synthesize unsignedLongLongValue;
@synthesize floatValue;
@synthesize doubleValue;
@synthesize decimalValue;
@synthesize objCType;
// Designated initializer - private method
- (NSMutableNumber *)initAllints:(unsigned long long)ULLongVal allFloats:(long double)LDoubleVal
{
boolValue = ULLongVal;
charValue = (char)ULLongVal;
unsignedCharValue = (unsigned char)ULLongVal;
shortValue = (short)ULLongVal;
unsignedShortValue = (unsigned short)ULLongVal;
intValue = (int)ULLongVal;
unsignedIntValue = (unsigned int)ULLongVal;
integerValue = (NSInteger)ULLongVal;
unsignedIntegerValue = (NSUInteger)ULLongVal;
longValue = ULLongVal;
unsignedLongValue = ULLongVal;
longLongValue = ULLongVal;
unsignedLongLongValue = ULLongVal;
floatValue = LDoubleVal;
doubleValue = LDoubleVal;
_longDoubleValue = LDoubleVal;
NSNumber *decimalNumber = [NSNumber numberWithUnsignedLongLong:LDoubleVal];
NSDecimal decimal = [decimalNumber decimalValue];
decimalValue = decimal;
return self;
}
// Private method
- (void)setAllIntValues:(unsigned long long)ULLongVal allFloats:(long double)LDoubleVal
{
boolValue = ULLongVal;
charValue = (char)ULLongVal;
unsignedCharValue = (unsigned char)ULLongVal;
shortValue = (short)ULLongVal;
unsignedShortValue = (unsigned short)ULLongVal;
intValue = (int)ULLongVal;
unsignedIntValue = (unsigned int)ULLongVal;
integerValue = (NSInteger)ULLongVal;
unsignedIntegerValue = (NSUInteger)ULLongVal;
longValue = ULLongVal;
unsignedLongValue = ULLongVal;
longLongValue = ULLongVal;
unsignedLongLongValue = ULLongVal;
floatValue = LDoubleVal;
doubleValue = LDoubleVal;
_longDoubleValue = LDoubleVal;
NSNumber *decimalNumber = [NSNumber numberWithUnsignedLongLong:LDoubleVal];
NSDecimal decimal = [decimalNumber decimalValue];
decimalValue = decimal;
}
+ (NSMutableNumber *)numberWithBool:(BOOL)value
{
return [[super alloc] initWithBool:value];
}
+ (NSMutableNumber *)numberWithChar:(char)value
{
return [[super alloc] initWithChar:value];
}
+ (NSMutableNumber *)numberWithUnsignedChar:(unsigned char)value
{
return [[super alloc] initWithUnsignedChar:value];
}
+ (NSMutableNumber *)numberWithShort:(short)value
{
return [[super alloc] initWithShort:value];
}
+ (NSMutableNumber *)numberWithUnsignedShort:(unsigned short)value
{
return [[super alloc] initWithUnsignedShort:value];
}
+ (NSMutableNumber *)numberWithInt:(int)value
{
return [[super alloc] initWithInt:value];
}
+ (NSMutableNumber *)numberWithUnsignedInt:(unsigned int)value
{
return [[super alloc] initWithUnsignedInt:value];
}
+ (NSMutableNumber *)numberWithInteger:(NSInteger)value
{
return [[super alloc] initWithInteger:value];
}
+ (NSMutableNumber *)numberWithUnsignedInteger:(NSUInteger)value
{
return [[super alloc] initWithUnsignedInteger:value];
}
+ (NSMutableNumber *)numberWithLong:(long)value
{
return [[super alloc] initWithLong:value];
}
+ (NSMutableNumber *)numberWithUnsignedLong:(unsigned long)value
{
return [[super alloc] initWithUnsignedLong:value];
}
+ (NSMutableNumber *)numberWithLongLong:(long long)value
{
return [[super alloc] initWithLongLong:value];
}
+ (NSMutableNumber *)numberWithUnsignedLongLong:(unsigned long long)value
{
return [[super alloc] initWithUnsignedLongLong:value];
}
+ (NSMutableNumber *)numberWithFloat:(float)value
{
return [[super alloc] initWithFloat:value];
}
+ (NSMutableNumber *)numberWithDouble:(double)value
{
return [[super alloc] initWithDouble:value];
}
+ (NSMutableNumber *)numberWithLongDouble:(long double)value
{
return [[super alloc] initWithLongDouble:value];
}
+ (NSMutableNumber *)numberWithDecimal:(NSDecimal)value
{
return [[super alloc] initWithDecimal:value];
}
- (NSMutableNumber *)initWithBool:(BOOL)value;
{
if (self = [super init]) {
objCType = @encode(BOOL);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithChar:(char)value
{
if (self = [super init]) {
objCType = @encode(char);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithUnsignedChar:(unsigned char)value
{
if (self = [super init]) {
objCType = @encode(unsigned char);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithShort:(short)value
{
if (self = [super init]) {
objCType = @encode(short);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithUnsignedShort:(unsigned short)value
{
if (self = [super init]) {
objCType = @encode(unsigned short);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithInt:(int)value
{
if (self = [super init]) {
objCType = @encode(int);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithUnsignedInt:(unsigned int)value
{
if (self = [super init]) {
objCType = @encode(unsigned int);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithInteger:(NSInteger)value
{
if (self = [super init]) {
objCType = @encode(NSInteger);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithUnsignedInteger:(NSUInteger)value
{
if (self = [super init]) {
objCType = @encode(NSUInteger);
self =[self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithLong:(long)value
{
if (self = [super init]) {
objCType = @encode(long);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithUnsignedLong:(unsigned long)value
{
if (self = [super init]) {
objCType = @encode(unsigned long);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithLongLong:(long long)value
{
if (self = [super init]) {
objCType = @encode(long long);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithUnsignedLongLong:(unsigned long long)value
{
if (self = [super init]) {
objCType = @encode(unsigned long long);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithFloat:(float)value
{
if (self = [super init]) {
objCType = @encode(float);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithDouble:(double)value
{
if (self = [super init]) {
objCType = @encode(double);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithLongDouble:(long double)value
{
if (self = [super init]) {
objCType = @encode(long double);
self = [self initAllints:value allFloats:value];
}
return self;
}
- (NSMutableNumber *)initWithDecimal:(NSDecimal)value
{
if (self = [super init]) {
objCType = @encode(NSDecimal);
decimalValue = value;
NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithDecimal:value];
unsigned long long UlongLongVal = [decimalNumber unsignedLongLongValue];
long double LDoubleVal = [decimalNumber doubleValue];
boolValue = UlongLongVal;
charValue = (char)UlongLongVal;
unsignedCharValue = (unsigned char)UlongLongVal;
shortValue = (short)UlongLongVal;
unsignedShortValue = (unsigned short)UlongLongVal;
intValue = (int)UlongLongVal;
unsignedIntValue = (unsigned int)UlongLongVal;
integerValue = (NSInteger)UlongLongVal;
unsignedIntegerValue = (NSUInteger)UlongLongVal;
longValue = (long)UlongLongVal;
unsignedLongValue = (unsigned long)UlongLongVal;
longLongValue = (long long)UlongLongVal;
unsignedLongLongValue = (unsigned long long)UlongLongVal;
floatValue = (float)LDoubleVal;
doubleValue = (double)LDoubleVal;
_longDoubleValue = LDoubleVal;
}
return self;
}
- (NSString *)stringValue
{
NSLocale *locale = [NSLocale systemLocale];
return [self descriptionWithLocale:locale];
}
- (NSString *)description
{
return [self stringValue];
}
- (NSString *)descriptionWithLocale:(NSLocale *)locale
{
NSString *description;
NSString *(^desc)(NSLocale *locale, NSString *format, ...);
desc = ^(NSLocale *locale, NSString *format, ...) {
va_list args;
va_start (args, format);
NSString *valueAsString = [[NSString alloc] initWithFormat:format locale:locale arguments:args];
va_end(args);
return valueAsString;
};
if (strcmp(objCType, @encode(BOOL)) == 0) {
if (self.boolValue) {
description = desc(locale, @"%YES");
} else {
description = desc(locale, @"%NO");
}
} else if (strcmp(objCType, @encode(char)) == 0) {
description = desc(locale, @"%hhi", self.charValue);
} else if (strcmp(objCType, @encode(unsigned char)) == 0) {
description = desc(locale, @"%hhu", self.unsignedCharValue);
} else if (strcmp(objCType, @encode(short)) == 0) {
description = desc(locale, @"%hd", self.shortValue);
} else if (strcmp(objCType, @encode(unsigned short)) == 0) {
description = desc(locale, @"%hu", self.unsignedShortValue);
} else if (strcmp(objCType, @encode(int)) == 0) {
description = desc(locale, @"%d", self.intValue);
} else if (strcmp(objCType, @encode(unsigned int)) == 0) {
description = desc(locale, @"%u", self.unsignedIntValue);
} else if (strcmp(objCType, @encode(NSInteger)) == 0) {
description = desc(locale, @"%ld", (long)self.integerValue);
} else if (strcmp(objCType, @encode(NSUInteger)) == 0) {
description = desc(locale, @"%lu", (long)self.unsignedIntegerValue);
} else if (strcmp(objCType, @encode(long)) == 0) {
description = desc(locale, @"%ld", self.longValue);
} else if (strcmp(objCType, @encode(unsigned long)) == 0) {
description = desc(locale, @"%lu", self.unsignedLongValue);
} else if (strcmp(objCType, @encode(long long)) == 0) {
description = desc(locale, @"%lld", self.longLongValue);
} else if (strcmp(objCType, @encode(unsigned long long)) == 0) {
description = desc(locale, @"%llu", self.unsignedLongLongValue);
} else if (strcmp(objCType, @encode(float)) == 0) {
description = desc(locale, @"%f", self.floatValue);
} else if (strcmp(objCType, @encode(double)) == 0) {
description = desc(locale, @"%lf", self.doubleValue);
} else if (strcmp(objCType, @encode(long double)) == 0) {
description = desc(locale, @"%Lf", self.longDoubleValue);
} else if (strcmp(objCType, @encode(NSDecimal)) == 0) {
NSDecimalNumber *decimal = [NSDecimalNumber decimalNumberWithDecimal:decimalValue];
description = desc(locale, @"%@", [decimal stringValue]);
}
return description;
}
- (void)setBoolValue:(BOOL)value
{
objCType = @encode(BOOL);
[self setAllIntValues:value allFloats:value];
}
- (void)setCharValue:(char)value
{
objCType = @encode(char);
[self setAllIntValues:value allFloats:value];
}
- (void)setUnsignedCharValue:(unsigned char)value
{
objCType = @encode(unsigned char);
[self setAllIntValues:value allFloats:value];
}
- (void)setShortValue:(short)value
{
objCType = @encode(short);
[self setAllIntValues:value allFloats:value];
}
- (void)setUnsignedShortValue:(unsigned short)value
{
objCType = (@encode(unsigned short));
[self setAllIntValues:value allFloats:value];
}
-(void)setIntValue:(int)value
{
objCType = @encode(int);
[self setAllIntValues:value allFloats:value];
}
-(void)setUnsignedIntValue:(unsigned int)value
{
objCType = @encode(unsigned int);
[self setAllIntValues:value allFloats:value];
}
- (void)setIntegerValue:(NSInteger)value
{
objCType = @encode(NSInteger);
[self setAllIntValues:value allFloats:value];
}
- (void)setUnsignedIntegerValue:(NSUInteger)value
{
objCType = @encode(NSUInteger);
[self setAllIntValues:value allFloats:value];
}
- (void)setLongValue:(long)value
{
objCType = @encode(long);
[self setAllIntValues:value allFloats:value];
}
- (void)setUnsignedLongValue:(unsigned long)value
{
objCType = @encode(unsigned long);
[self setAllIntValues:value allFloats:value];
}
- (void)setLongLongValue:(long long)value
{
objCType = @encode(long long);
[self setAllIntValues:value allFloats:value];
}
- (void)setUnsignedLongLongValue:(unsigned long long)value
{
objCType = @encode(unsigned long long);
[self setAllIntValues:value allFloats:value];
}
- (void)setFloatValue:(float)value
{
objCType = @encode(float);
[self setAllIntValues:value allFloats:value];
}
- (void)setDoubleValue:(double)value
{
objCType = @encode(double);
[self setAllIntValues:value allFloats:value];
}
- (void)setLongDoubleValue:(long double)value
{
objCType = @encode(long double);
[self setAllIntValues:value allFloats:value];
}
- (void)setDecimalValue:(NSDecimal)value
{
objCType = @encode(NSDecimal);
decimalValue = value;
NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithDecimal:value];
unsigned long long UlongLongVal = [decimalNumber unsignedLongLongValue];
long double LDoubleVal = [decimalNumber doubleValue];
boolValue = UlongLongVal;
charValue = (char)UlongLongVal;
unsignedCharValue = (unsigned char)UlongLongVal;
shortValue = (short)UlongLongVal;
unsignedShortValue = (unsigned short)UlongLongVal;
intValue = (int)UlongLongVal;
unsignedIntValue = (unsigned int)UlongLongVal;
integerValue = (NSInteger)UlongLongVal;
unsignedIntegerValue = (NSUInteger)UlongLongVal;
longValue = (long)UlongLongVal;
unsignedLongValue = (unsigned long)UlongLongVal;
longLongValue = (long long)UlongLongVal;
unsignedLongLongValue = (unsigned long long)UlongLongVal;
floatValue = (float)LDoubleVal;
doubleValue = (double)LDoubleVal;
_longDoubleValue = LDoubleVal;}
@end