【问题标题】:Why does this conditional cause an error?为什么这个条件会导致错误?
【发布时间】:2019-06-11 08:19:45
【问题描述】:

我有一个包含几个条件的方法。第一个条件工作正常,不会引起任何问题。但是,第二个会导致应用崩溃。

- (void)didReceiveGaiaGattResponse:(CSRGaiaGattCommand *)command
{
    GaiaCommandType cmdType = [command getCommandId];
    NSData *requestPayload = [command getPayload];
    uint8_t success = 0;

    NSLog(@"cmdType: %li", (long)cmdType);
    [requestPayload getBytes:&success range:NSMakeRange(0, sizeof(uint8_t))];

    if (cmdType == GaiaCommand_GetCurrentBatteryLevel && requestPayload.length > 1)
    {
        uint16_t value = 0;
        [requestPayload getBytes:&value range:NSMakeRange(1, sizeof(uint16_t))];
        NSInteger battery = CFSwapInt16BigToHost(value);

        [self sendEventWithName:someDEVICE_BATTERY_CHANGED body:@{@"batteryLevel":[NSNumber numberWithInteger:battery]}];
        return;
    }
     else if (cmdType == GaiaCommand_GET_FBC && requestPayload.length > 1)
    {
         uint16_t value = 0;
         [requestPayload getBytes:&value range:NSMakeRange(1, sizeof(uint16_t))];
         NSInteger feedbackCancellationMode = CFSwapInt16BigToHost(value);
         [self sendEventWithName:FEEDBACK_CANCELLATION_MODE body:@{@"feedbackCancellationMode": [NSNumber numberWithInt:feedbackCancellationMode]}];
         return;
    }

    //do more stuff
}

条件

if (cmdType == GaiaCommand_GetCurrentBatteryLevel && requestPayload.length > 1)

工作没有问题。

但是,有条件的

else if (cmdType == GaiaCommand_GET_FBC && requestPayload.length > 1)

在 xcode 中导致以下警告

隐式转换丢失整数精度:“NSInteger”(又名“long”) 到'int'

另外,我在调试器中也看到了错误提示

* 由于未捕获的异常“NSRangeException”而终止应用,原因:“* -[_NSInlineData getBytes:range:]:范围 {1, 2} 超出

数据长度 2'

【问题讨论】:

    标签: objective-c nsinteger nsrangeexception


    【解决方案1】:

    想想这告诉你什么:

    Terminating app due to uncaught exception 'NSRangeException', reason:
    '-[_NSInlineData getBytes:range:]: range {1, 2} exceeds data length 2'
    

    您的数据对象长度为 2 个字节。第一个字节,位置 0,是(根据您的代码)success 值。这会在位置 1 处多留一个字节来处理。但是您的代码试图从中复制 2 个字节——即消息中的 range {1, 2};从位置 1 开始,长度为 2 的范围。您正在读取数据的末尾。

    您必须检查数据是否有足够的数据来满足您尝试进行的-getBytes:... 调用。您可能还需要更正您对缓冲区中取消模式值应该有多大的假设,因为它显然比您预期的要小。您的代码假定它是 uint16_t(2 个字节),但数据中只剩下一个字节。

    【讨论】:

    • 取消模式应该返回 0 或 1。或者它可能会返回 00 或 01。我不确定如何相应地调整代码。一般来说,我对 Objective C 和原生模块非常陌生/不熟悉(我通常只使用 React Native。
    • 知道它是 0 还是 1 是不够的。您需要知道您接收的数据的布局。数据缓冲区中的每个值在哪里,它们有多少字节?如果取消模式预计只有一个字节,则将该分支中value 的类型更改为uint8_t,并将您拥有sizeof(uint16_t) 的位置更改为sizeof(value)。并删除对CFSwapInt16BigToHost()的调用;只需将value 分配给feedbackCancellationMode
    • 这正是我所需要的!非常感谢!
    【解决方案2】:
    [NSNumber numberWithInt:feedbackCancellationMode]}]
    

    应该是

    [NSNumber numberWithInteger: feedbackCancellationMode]}]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多