2016-03-02 3 views
4

Оказывается, что valueForKey: с BOOL@property имя для ключа возвращает различные типы (и, следовательно, приводит к различным JSON сериализации) на 64-битных и 32-битных систем IOS:BOOL собственность KVC: это поведение ошибка?

На 32-битной (4s картинки имитатора):

8 * sizeof(void*) = 32 
boolProperty attributes: Tc,N,V_boolProperty 
obj.boolProperty = YES 
[obj valueForKey:@"boolProperty"]: 1 
[[obj valueForKey:@"boolProperty"] class]: __NSCFNumber 
JSON serialization of @{ @"boolProperty": [obj valueForKey:@"boolProperty"] }: {"boolProperty":1} 
obj.boolProperty = NO 
[obj valueForKey:@"boolProperty"]: 0 
[[obj valueForKey:@"boolProperty"] class]: __NSCFNumber 
JSON serialization of @{ @"boolProperty": [obj valueForKey:@"boolProperty"] }: {"boolProperty":0} 

на 64-разрядных (iPhone 6 имитатора):

8 * sizeof(void*) = 64 
boolProperty attributes: TB,N,V_boolProperty 
obj.boolProperty = YES 
[obj valueForKey:@"boolProperty"]: 1 
[[obj valueForKey:@"boolProperty"] class]: __NSCFBoolean 
JSON serialization of @{ @"boolProperty": [obj valueForKey:@"boolProperty"] }: {"boolProperty":true} 
obj.boolProperty = NO 
[obj valueForKey:@"boolProperty"]: 0 
[[obj valueForKey:@"boolProperty"] class]: __NSCFBoolean 
JSON serialization of @{ @"boolProperty": [obj valueForKey:@"boolProperty"] }: {"boolProperty":false} 

код:

@interface TSTObject : NSObject 

@property (nonatomic, assign) BOOL boolProperty; 

@end 

[…] 

NSLog(@"8 * sizeof(void*) = %lu", 8 * sizeof(void*)); 

objc_property_t boolProp = class_getProperty([TSTObject class], "boolProperty"); 
NSLog(@"boolProperty attributes: %s", property_getAttributes(boolProp)); 

void(^testBool)(BOOL) = ^(BOOL boolValue) { 
    TSTObject *obj = [[TSTObject alloc] init]; 
    id vfk; 
    obj.boolProperty = boolValue; 
    vfk = [obj valueForKey:@"boolProperty"]; 
    NSLog(@"obj.boolProperty = %@", boolValue ? @"YES" : @"NO"); 
    NSLog(@"[obj valueForKey:@\"boolProperty\"]: %@", vfk); 
    NSLog(@"[[obj valueForKey:@\"boolProperty\"] class]: %@", [vfk class]); 
    NSLog(@"JSON serialization of @{ @\"boolProperty\": [obj valueForKey:@\"boolProperty\"] }: %@", 
      [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:@{@"boolProperty": vfk} 
                     options:0 
                      error:NULL] 
           encoding:NSUTF8StringEncoding]); 
}; 

testBool(YES); 
testBool(NO); 

Все это с симуляторами Xcode 7.2, iOS 9.2.

Вполне вероятно, что основной причиной является, по словам this answer:

Примечание: На 64-битной платформе IOS (а не на 64-битной OS X), BOOL определяется как C99 _Bool, который является «правильным» булевым типом и может принимать только значение 0 или 1.

Это причина?

Это ошибка или предполагаемое поведение?

ответ

1

Да, это причина.

Да, это предназначенное поведение. (Ну, то, как он сериализуется в JSON на 32-битной, не особенно «предназначен», но ожидается. Тот факт, что используется 64-битный тип подходящего типа Bool, предназначен.)

Сериализатор JSON не имеет никакого способа чтобы разделить однобайтное целое число со знаком и логическое на 32-битном, потому что они на самом деле одно и то же.

+0

Простейшим решением может быть обращение к экземплярам 'NSNumber', обертывающим примитивы во время кодирования/декодирования JSON. – mszaro

+0

Справедливости ради стоит сказать, что среда выполнения ObjC на 32-разрядной iOS не имеет возможности отличить свойство BOOL от свойства 'signed char'? – Isaac

+1

Это правильно, потому что это одно и то же. 'BOOL' - всего лишь тип для' подписанного символа' на 32-битном. –

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