简体   繁体   English

使用 NSPredicate 按 NSNumber 过滤自定义对象数组时遇到问题

[英]Trouble filtering array of custom objects by an NSNumber using NSPredicate

This should be straightforward but something is preventing me from filtering an array of custom objects by NSNumber using NSPredicate.这应该很简单,但有些东西阻止我使用 NSPredicate 通过 NSNumber 过滤自定义对象数组。 Perhaps it has something to do with the datatype when converting from JSON but I can't figure it out.从 JSON 转换时,它可能与数据类型有关,但我无法弄清楚。

I download data from a JSON in an array of custom Objects that look like:我从 JSON 下载了一组自定义对象中的数据,如下所示:

{"hid":"47","public":"1"}

The code to parse the JSON looks like:解析 JSON 的代码如下所示:

 if (feedElement[@"public"] && ![feedElement[@"public"] isEqual:[NSNull null]]) {
            newMyObject.pub = feedElement[@"public"]== nil ? @"0" : feedElement[@"public"];}

The object looks like: object 看起来像:

#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MyObject : NSObject
@property (nonatomic, retain) NSNumber * hid; 
@property (nonatomic, retain) NSNumber * pub;
@end
NS_ASSUME_NONNULL_END

The objects are placed in an NSArray * myObjects对象被放置在一个 NSArray * myObjects

My NSPredicate and filter code looks like:我的 NSPredicate 和过滤器代码如下所示:

NSPredicate *pubPred = [NSPredicate predicateWithFormat:@"pub == 1"];
NSArray *filteredArray = [myObjects filteredArrayUsingPredicate:pubPred];

When I log [myObjects valueForKey:@"pub"] , it logs as 1,1,1, etc. so I know that the values for pub are all 1 however the resulting filteredArray is empty.当我记录[myObjects valueForKey:@"pub"]时,它记录为 1,1,1 等,所以我知道 pub 的值都是 1,但是生成的filteredArray是空的。

What could be wrong with my code?我的代码可能有什么问题?

Thanks for any suggestions.感谢您的任何建议。

Edit : I changed public to pub in the object in case public was a reserved word but it did not change anything编辑:我在 object 中将 public 更改为 pub 以防 public 是保留字但它没有改变任何东西

With sample code: {"hid":"47","public":"1"}带有示例代码: {"hid":"47","public":"1"}

newMyObject.pub = feedElement[@"public"]== nil ? @"0" : feedElement[@"public"];

In case of public value is present in JSON, you'll set pub property with feedElement[@"public"] , which means, it will be @"1" (with the sample), which means you'll put a NSString .如果 JSON 中存在public值,您将使用feedElement[@"public"]设置pub属性,这意味着它将是 @"1"(带有示例),这意味着您将放置一个NSString
In case of public value is present in JSON, you'll set pub property with @"0" which means you'll put a NSString .如果 JSON 中存在public值,您将使用 @"0" 设置pub属性,这意味着您将放置一个NSString

It doesn't matter if it's declared @property (nonatomic, retain) NSNumber * pub;是否声明@property (nonatomic, retain) NSNumber * pub;没关系, you are setting a NSString , not a NSNumber . ,您正在设置NSString ,而不是NSNumber

Want some code testing?想要一些代码测试?

@interface MyObject : NSObject

@property (nonatomic, retain) NSNumber *hid;
@property (nonatomic, retain) NSNumber *pub;

+(void)test;
@end

And

@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);
}

Output: Output:

$> Filtered-NSNumber: (
    "<MyObject: 0x60000024cba0> pub: 1 - hid: 3"
)
$> Filtered-NSString: (
    "<MyObject: 0x60000024d1e0> pub: 1 - hid: 2"
)

You can state: "Yeah, but you have a warning in [[MyObject alloc] initWithPub:@"1" andHID:@"2"] : Incompatible pointer types sending 'NSString *' to parameter of type 'NSNumber *' , yes, I have. You should have it too.您可以 state:“是的,但是在[[MyObject alloc] initWithPub:@"1" andHID:@"2"]中有警告: Incompatible pointer types sending 'NSString *' to parameter of type 'NSNumber *' ,是的,我有。你也应该有。

In fact, you'll have it too if you wrote your ternary if:事实上,如果你写了你的三元组,你也会拥有它,如果:

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

What about using this to your code to check:如何使用它来检查您的代码:

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]);
}

You should get a -[__NSCFConstantString stringValue]: unrecognized selector sent to instance error, because it's really a NSString , not a NSNumber .你应该得到一个-[__NSCFConstantString stringValue]: unrecognized selector sent to instance错误,因为它实际上是一个NSString ,而不是一个NSNumber

Solutions:解决方案:

You need to fix your parsing, or change the type of property in MyObject .您需要修复解析,或更改MyObject中的属性类型。

With keeping the property as a NSNumber :将属性保留为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 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM