2009-11-05 2 views
3

Я довольно новичок в Objective-C (и сам C) и должен потреблять NSData с выхода HTTP. Я никогда не работал с байтовыми массивами или не беспокоился о проблемах с маленькими/большими концами, и немного пытался написать следующий метод для чтения NSNumber с указанной длиной от NSData.Чтение NSNumber из NSData

- (NSNumber *)readNumberWithLength:(NSUInteger)length 
{ 
    Byte k[length]; 
    [data getBytes:k range:NSMakeRange(offset, length)]; // big endian byte array representing a number 
    offset += length; 

    NSNumber *number; 
    if (length==4) { 
     number = [NSNumber numberWithUnsignedInt:CFSwapInt32BigToHost(*(uint32_t *)k)]; 
    } else if (length==2) { 
     number = [NSNumber numberWithUnsignedShort:CFSwapInt16BigToHost(*(uint16_t *)k)]; 
    } else if (length==1) { 
     number = [NSNumber numberWithUnsignedChar:*(uint8_t *)k]; 
    } else if (length==8) { 
     number = [NSNumber numberWithUnsignedLongLong:CFSwapInt64BigToHost(*(uint64_t *)k)]; 
    } else { 
     number = [NSNumber numberWithInt:0]; 
    } 

    return number; 
} 

NSData *data меня и NSUInteger offset объявлены как переменные экземпляра.

Правильно ли этот код? О чем я должен беспокоиться? Я еще не тестировал его на самом устройстве (только на симуляторе), и, похоже, он отлично работает для меня. Есть ли у вас какие-либо комментарии по этому поводу?

Спасибо!

ответ

2

Код выглядит более или менее верным.

Кажется, что это трудный путь.

Я был бы удивлен - не полностью потрясен, но удивлен, что данные, возвращаемые с HTTP-сервера, действительно являются просто сырыми байтами. Было бы крайне редко, что это так, и в случае, если это так, дизайн сервера почти наверняка ошибочен. (Есть, конечно, случаи, когда ответ двоично-HTTP-ответа - правильный ответ, но он очень редок).

Если вы не говорите о 100 тысячах значений в данных, накладные расходы, связанные с HTTP, почти наверняка перевесят любые выгоды от перехода на двоичный код. Разбор известных числовых значений из строки не равен , что обременительно, если вы действительно не делаете этого постоянно (что сделало бы использование HTTP не особенно привлекательным в первую очередь).


Дизайн сервера: достаточно честный. Еще одна важная причина для этого - это потому, что вы не можете изменить эту часть головоломки.

Я бы лично реализовать код более оборонительно:

  • проверить, что локальные размеры данных имеют ожидаемых размеров по сравнению с удаленных/сетевых размеров, чтобы избежать неприятных сюрпризов (это может быть утверждения об инициализации или в некоторый код отладки - я предпочитаю быть защищенным в таких ситуациях).

  • используйте оператор case вместо последовательности if/else if/else if/else. Полностью эстетическое решение, но оно будет способствовать ...

  • ... имеет значение length, являющееся неожиданным значением путем ведения журнала, даже если он находится только в режиме отладки. Я думаю, что неожиданный размер ценности потенциально очень плохо для общей правильности?

+0

Это RESTful API, и он действительно отвечает на коллекции сотен значений (строк и чисел). Выходной файл gziped, поэтому он имеет смысл для меня. Я на самом деле не проектировал сервер, и он не изменится, поэтому меня больше волнует, как будто моя реализация правильная. Как вы думаете, есть ли лучший способ сделать это? Благодаря! – leolobato

+0

Спасибо за советы! Меня действительно беспокоило то, как я делал преобразование байтового массива в nsnumber, но так как вы не упомянули эту часть, похоже, что это правильно (или, по крайней мере, допустимый способ). :) – leolobato

Смежные вопросы