Оказывается, что 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.
Это причина?
Это ошибка или предполагаемое поведение?
Простейшим решением может быть обращение к экземплярам 'NSNumber', обертывающим примитивы во время кодирования/декодирования JSON. – mszaro
Справедливости ради стоит сказать, что среда выполнения ObjC на 32-разрядной iOS не имеет возможности отличить свойство BOOL от свойства 'signed char'? – Isaac
Это правильно, потому что это одно и то же. 'BOOL' - всего лишь тип для' подписанного символа' на 32-битном. –