С примером кода: {"hid":"47","public":"1"}
newMyObject.pub = feedElement[@"public"]== nil ? @"0" : feedElement[@"public"];
Если значение public
присутствует в JSON, вы установите свойство pub
с feedElement[@"public"]
, что означает, что оно будет @ "1" (с образцом), что означает, что вы положите NSString
.
. В случае public
значение присутствует в JSON, вы установите свойство pub
с помощью @ «0» означает, что вы поставите NSString
.
. Неважно, объявлено ли оно @property (nonatomic, retain) NSNumber * pub;
, вы устанавливаете NSString
, а не NSNumber
.
Хотите тестирование кода?
@interface MyObject : NSObject
@property (nonatomic, retain) NSNumber *hid;
@property (nonatomic, retain) NSNumber *pub;
+(void)test;
@end
И
@implementation MyObject
-(id)initWithPub:(NSNumber *)pub andHID:(NSNumber *)hid {
self = [super init];
if (self) {
self.pub = pub;
self.hid = hid;
}
return self;
}
-(NSString *)description {
return [NSString stringWithFormat:@"%@ pub: %@ - hid: %@", [super description], [self pub], [self hid]];
}
+(NSArray *)arrayList {
return @[[[MyObject alloc] initWithPub:@1 andHID:@3], //Here with real NSNUmbner
[[MyObject alloc] initWithPub:@"1" andHID:@"2"]]; //Here with NSString instead
}
+(void)test {
NSArray *list = [MyObject arrayList];
NSPredicate *predicateNSNumber = [NSPredicate predicateWithFormat:@"pub == %@", @1];
NSArray *filteredNSNumber = [list filteredArrayUsingPredicate:predicateNSNumber];
NSLog(@"Filtered-NSNumber: %@", filteredNSNumber);
NSPredicate *predicateNSString = [NSPredicate predicateWithFormat:@"pub == %@", @"1"];
NSArray *filteredNSString = [list filteredArrayUsingPredicate:predicateNSString];
NSLog(@"Filtered-NSString: %@", filteredNSString);
}
Вывод:
$> Filtered-NSNumber: (
"<MyObject: 0x60000024cba0> pub: 1 - hid: 3"
)
$> Filtered-NSString: (
"<MyObject: 0x60000024d1e0> pub: 1 - hid: 2"
)
Вы можете заявить: «Да, но у вас есть предупреждение в [[MyObject alloc] initWithPub:@"1" andHID:@"2"]
: Incompatible pointer types sending 'NSString *' to parameter of type 'NSNumber *'
, да, у меня есть. У вас тоже должно быть это.
На самом деле, оно у вас тоже будет, если вы написали свою троицу, если:
if (feedElement[@"public"] == nil) {
newMyObject.pub = @"0"; //Incompatible pointer types assigning to 'NSNumber * _Nonnull' from 'NSString *'
} else {
newMyObject.pub = feedElement[@"public"]; //Here, no warning, because it's hope you know what you are doing and setting a NSNumber here.
}
Как насчет использования этого в вашем коде для проверки:
for (MyObject *anObject in list) {
NSLog(@"Testing: %@", anObject);
if ([[anObject pub] isKindOfClass:[NSString class]]) {
NSLog(@"Pub is a String");
} else if ([[anObject pub] isKindOfClass:[NSNumber class]]) {
NSLog(@"Pub is a NSNumber");
}
NSLog(@"Attempt to call -stringValue which is a NSNumber method, not a NSString one");
NSLog(@"Attempt Call: %@\n", [[anObject pub] stringValue]);
}
Вы должны получить ошибку -[__NSCFConstantString stringValue]: unrecognized selector sent to instance
, потому что это действительно NSString
, а не NSNumber
.
Решения:
Вам нужно исправить парсинг или изменить тип свойства в MyObject
.
С keepin г собственности как NSNumber
:
if ([feedElement[@"public"] isKindOfClass:[NSString class]]) {
self.pub = @([feedElement[@"public"] integerValue]); //Transform it into a NSInteger, then into a NSNumber with @(someInteger)
} else ([feedElement[@"public"] isKindOfClass:[NSNumber class]]) {
self.pub = feedElement[@"public"]; //It's already a NSNumber instance
} else {
self.pub = @(0); //Default value because unknown class or not present
}