【问题标题】:Why does this Creation of NSDecimalNumber crash?为什么创建 NSDecimalNumber 会崩溃?
【发布时间】:2017-04-17 08:36:59
【问题描述】:

我正在从云服务下载一些值作为 JSON 对象并将它们分配给 NSString 对象,如下所示

NSString *price = [orpObjectDict objectForKey:@"price"];
NSString *qty = [orpObjectDict objectForKey:@"qty"];

我的调试输出显示两个字符串的值如下

NSLog(@"price: %@ <--> qty: %@", price, qty);

2017-04-17 16:29:05.665043 NWMobileTill[1490:730225] price: 6.95 <--> qty: 1

但是下面使用这些 NSStrings 创建 NSDecimalNumber 失败

NSDecimalNumber *priceNumber = [NSDecimalNumber decimalNumberWithString:price];
NSDecimalNumber *qtyNumber = [NSDecimalNumber decimalNumberWithString:qty];

017-04-17 16:29:05.665886 NWMobileTill[1490:730225] -[__NSCFNumber length]: unrecognized selector sent to instance 0x174226240
2017-04-17 16:29:05.668080 NWMobileTill[1490:730225] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber length]: unrecognized selector sent to instance 0x174226240'
*** First throw call stack:
(0x1926fd1b8 0x19113455c 0x192704268 0x192701270 0x1925fa80c 0x19323658c 0x1932340f0 0x193234754 0x1000d9078 0x192cff1e8 0x192d17120 0x1931ebfb0 0x193130aa8 0x1931210a4 0x1931ee35c 0x1006c5218 0x1006d2aec 0x1006c8ce0 0x1006d4e2c 0x1006d4b78 0x19178f2a0 0x19178ed8c)
libc++abi.dylib: terminating with uncaught exception of type NSException

为什么这个简单的创建会崩溃?

【问题讨论】:

  • Objective-C 在对象类型方面相当松散;特别是,NSDictionaryheterogeneous 并且可以包含任何内容。我会确保qty 实际上是NSString
  • 我如何确保它是?你可以看到我将它分配给一个 NSString,如果这还不够,我怎样才能确保它是双重的?
  • 我认为if ([qty isKindOfClass: [NSString class]]) { ... 应该告诉你它是否是一个字符串。此外,在调试器中设置断点并将鼠标悬停在变量上应该会告诉您。

标签: ios objective-c nsdecimalnumber


【解决方案1】:

你得到的是数字,你正在将代码写成字符串

请将此代码写成字符串格式

 NSString *price = [NSString stringWithFormat:@"%@", orpObjectDict objectForKey:@"price"];
 NSString *qty = [ [NSString stringWithFormat:@"%@",orpObjectDict objectForKey:@"qty"];

或者直接检查

if [price isKindOfClass:[NSString class]]
{  // It is string
}
else if [price isKindOfClass:[NSNumber class]]
{
  // It is number
}

【讨论】:

    【解决方案2】:

    错误信息

    [__NSCFNumber 长度]:无法识别的选择器发送到实例 0x174226240

    非常清楚:它表明键 price 的对象是 NSNumber 对象。

    所以你必须从NSNumber 创建一个NSDecimalNumber

    NSNumber *price = orpObjectDict[@"price"];
    NSDecimalNumber *priceNumber = [NSDecimalNumber decimalNumberWithDecimal:price.decimalValue];
    

    【讨论】:

      【解决方案3】:

      您可以使用 NSDecimalNumber 通过键直接检索您的对象:

      NSDictionary*orpObjectDict = @{
                                     @"price" : @(5.4),
                                     @"qty" : @(2)
                                     };
      NSString *price = [orpObjectDict objectForKey:@"price"];
      NSLog(@"string price %@", price);
      
      NSString *qty = [orpObjectDict objectForKey:@"qty"];
      NSLog(@"string qty %@", qty);
      
      NSDecimalNumber*dPrice = [orpObjectDict objectForKey:@"price"];
      NSLog(@"decimal price %@", dPrice);
      
      NSDecimalNumber *dqty = [orpObjectDict objectForKey:@"qty"];
      NSLog(@"decimal quantity %@", dqty);
      

      输出是:

      2017-04-17 10:46:12.932 test[2836:50653] string price 5.4
      2017-04-17 10:46:12.932 test[2836:50653] string qty 2
      2017-04-17 10:46:12.933 test[2836:50653] decimal price 5.4
      2017-04-17 10:46:12.933 test[2836:50653] decimal quantity 2
      

      您始终可以使用isKindOfClassisMemberOfClass 来检查返回对象类型,后者更具限制性。

      根据经验,在分配之前确保字典包含键及其值不是nil

      id value = dictionary[key];
      if (value) {...}
      

      或者为了更好的检查:

      if (value && value != [NSNull null]) {...}
      

      编辑

      我认为 Objective C 的类型管理比 Swift 弱。无论如何,使用[NSDecimalNumber alloc] initWithString: 方法可以为您提供正确的实例。

      NSDictionary*orpObjectDict = @{
                                     @"price" : @"5.4",
                                     @"qty" : @(2)
                                     };
      NSString* price = [orpObjectDict objectForKey:@"price"];
      NSLog(@"string price %@", price);
      
      NSDecimalNumber*decimalPrice = [[NSDecimalNumber alloc] initWithString:price];
      if ([decimalPrice isMemberOfClass:NSDecimalNumber.class]) {
          NSLog(@"dqty is a NSDecimalNumber");
      }
      

      【讨论】:

      • dPrice 不会是 NSDecimalNumber 实例。
      猜你喜欢
      • 2012-04-20
      • 1970-01-01
      • 2013-01-31
      • 2014-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-11
      相关资源
      最近更新 更多