Почему это условие вызывает ошибку?

У меня есть метод, который содержит несколько условных выражений. Первый условный работает нормально и не вызывает никаких проблем. Однако второй вызывает сбой приложения.

- (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
}

условное

если (cmdType == GaiaCommand_GetCurrentBatteryLevel && requestPayload.length > 1)

работает без проблем.

Тем не менее, условно

иначе если (cmdType == GaiaCommand_GET_FBC && requestPayload.length > 1)

вызывает следующее предупреждение в xcode

Неявное преобразование теряет целочисленную точность: «NSInteger» (он же «long») в «int»

Кроме того, я также видел сообщение об ошибке в отладчике

* Завершение работы приложения из-за необработанного исключения "NSRangeException", причина: "* -[_NSInlineData getBytes:range:]: диапазон {1, 2} превышает

длина данных 2'


person VK1    schedule 11.06.2019    source источник


Ответы (2)


Подумайте, что это говорит вам:

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 байта), но в данных остался только один байт.

person Ken Thomases    schedule 12.06.2019
comment
Режим отмены должен возвращать либо 0, либо 1. Или, может быть, он возвращает либо 00, либо 01. Я не уверен, как соответствующим образом настроить код. Я очень новичок/не знаком с Objective C и нативными модулями в целом (обычно я просто работаю с React Native. - person VK1; 12.06.2019
comment
Знать, что это либо 0, либо 1, недостаточно. Вам нужно знать структуру данных, которые вы получаете. Где находится каждое значение в буфере данных и сколько байтов они имеют? Если ожидается, что режим отмены будет состоять только из одного байта, измените тип value в этой ветке на uint8_t и измените место, где у вас есть sizeof(uint16_t), на sizeof(value). И удалите вызов CFSwapInt16BigToHost(); просто назначьте value на feedbackCancellationMode. - person Ken Thomases; 12.06.2019
comment
Это было именно то, что мне было нужно! Огромное спасибо! - person VK1; 13.06.2019

[NSNumber numberWithInt:feedbackCancellationMode]}]

должно быть

[NSNumber numberWithInteger: feedbackCancellationMode]}]
person VK1    schedule 12.06.2019