我的代码是
// NSDecimalNumber *percentSpent = [distributionModel.spent decimalNumberByDividingBy:self.monthlySummaryModel.totalSpent];
// NSLog(@"percent:%@", percentSpent);
NSLog(@"spent:%@, totalSpent:%@", distributionModel.spent, self.monthlySummaryModel.totalSpent);
其中
@property (nonatomic, strong) NSDecimalNumber *spent;
@property (nonatomic) NSDecimalNumber *totalSpent;
当percentSpent
被注释掉
2014-12-01 15:38:20.161 app-ios[15980:60b] spent:27.01, totalSpent:2077.01
2014-12-01 15:38:20.201 app-ios[15980:60b] spent:2000, totalSpent:2077.01
2014-12-01 15:38:20.251 app-ios[15980:60b] spent:40, totalSpent:2077.01
2014-12-01 15:38:20.292 app-ios[15980:60b] spent:10, totalSpent:2077.01
当我执行计算percentSpent
2014-12-01 15:35:44.843 app-ios[15963:60b] -[__NSCFNumber decimalNumberByDividingBy:]: unrecognized selector sent to instance 0x17d4f020
2014-12-01 15:35:44.851 app-ios[15963:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber decimalNumberByDividingBy:]: unrecognized selector sent to instance 0x17d4f020'
*** First throw call stack:
(0x2eaadf83 0x3925eccf 0x2eab1917 0x2eab0203 0x2e9ff768 0xac64b 0x313fd8f7 0x313a4c27 0x313a447d 0x312cad59 0x30f4862b 0x30f43e3b 0x30f43ccd 0x30f436df 0x30f434ef 0x30f3d21d 0x2ea79255 0x2ea76bf9 0x2ea76f3b 0x2e9e1ebf 0x2e9e1ca3 0x338e7663 0x3132e14d 0xa48cd 0x3976bab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
Signal: 6 (signal SIGABRT)
更新
@interface MonthlySummaryModel : NSObject
@property (nonatomic) int year;
@property (nonatomic) int month;
@property (nonatomic) NSDecimalNumber *totalSpent;
@property (nonatomic, strong) NSArray *distributions;
和
@interface MonthlySummaryDistributionModel : NSObject
@property (nonatomic, strong) NSString *group;
@property (nonatomic, strong) NSDecimalNumber *spent;
- (MonthlySummaryDistributionModel *) initWithJson: (NSDictionary *) json;
@end
这里有什么问题?
答案 0 :(得分:3)
您已崩溃,因为您已将NSDecimalNumber消息发送到不 NSDecimalNumber - 它是NSNumber。您可能认为它是一个NSDecimalNumber,显然您确实认为,正如您的评论所示:
但我将
spent
作为NSDecimalNumber
...但你错了。相信运行时,而不是你的直觉。运行时比你知道的更清楚(显然)这是什么类型的对象!
为什么会这样?你是如何让自己陷入这种境地的?我会解释一下。
Objective-C是多态。这意味着你如何宣告一件事并不重要;重要的是是什么。他们可以是不同的!原因是你可以关闭类型检查(意外),从而为任何变量分配一个完全错误类型的对象。
例如(拿着我的啤酒并观看此):
NSString* s;
NSNumber* n = [NSNumber new];
NSArray* arr = @[n];
s = arr[0];
想想我刚刚做了什么。我将一个NSNumber放入一个数组中,再将它拉出来,并将其分配给一个NSString变量!并且编译器没有阻止我!!!!!这是因为从NSArray中取出一些东西会关闭编译器对该东西的类型检查 - 你可以将它分配给任何,因为编译器不知道什么类型的真的是它。
但它仍然在现实生活中具有类型。因此,当程序运行时,以及在此之后向s
发送NSString消息时,您将崩溃,因为它不是 NSString,尽管声明。
这是意外地从编译器中隐藏某些类型的一个例子。有时,人们会做更糟糕的事情;他们故意隐藏编译器中的某些类型。例如(再次拿着我的啤酒):
NSString* s;
NSNumber* n = [NSNumber new];
s = (NSString*) n;
哇!那个时候我只是直接向编译器说谎,并告诉它NSNumber是一个NSString !!!!!编辑耸了耸肩说道:"好吧,等等。我猜他知道我不知道的事情。"所以它让我这样做,它让我将NSNumber分配给NSString变量。
但又一次,它仍然是一个NSNumber。因此,当我们尝试将其视为NSString时,我们将在运行时崩溃。
故事的寓意是:不要骗编译器!让 it 尽可能判断事物的类型。