ios - 使用 NSPredicate 按 NSNumber 过滤自定义对象数组时遇到问题
问题描述
这应该很简单,但有些东西阻止我使用 NSPredicate 通过 NSNumber 过滤自定义对象数组。也许它与从 JSON 转换时的数据类型有关,但我无法弄清楚。
我从一组自定义对象中的 JSON 下载数据,如下所示:
{"hid":"47","public":"1"}
解析 JSON 的代码如下所示:
if (feedElement[@"public"] && ![feedElement[@"public"] isEqual:[NSNull null]]) {
newMyObject.pub = feedElement[@"public"]== nil ? @"0" : feedElement[@"public"];}
该对象看起来像:
#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
对象被放置在一个 NSArray * myObjects
我的 NSPredicate 和过滤器代码如下所示:
NSPredicate *pubPred = [NSPredicate predicateWithFormat:@"pub == 1"];
NSArray *filteredArray = [myObjects filteredArrayUsingPredicate:pubPred];
当我登录[myObjects valueForKey:@"pub"]
时,它会记录为 1、1、1 等,所以我知道 pub 的值都是 1,但结果filteredArray
是空的。
我的代码可能有什么问题?
感谢您的任何建议。
编辑:我在对象中将 public 更改为 pub 以防 public 是保留字但它没有改变任何东西
解决方案
带有示例代码:{"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;
,你设置的是 a NSString
,而不是 a 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 ,您也会拥有它:
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
错误,因为它真的是 a NSString
,而不是 a NSNumber
。
解决方案:
您需要修复解析,或更改MyObject
.
将财产保持为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
}
推荐阅读
- java - Spring Boot中的一个类的多个配置树
- python - 如何将 dict 中的列表项与 Python 中的另一个列表相乘
- sql - 一个SQL问题,一个订单有多个产品
- firebase - Firebase 中的 IVR 支持
- r - ggplot polar_coord 更好地分隔文本
- java - 如何使用 Vaadin 实现 OAuth2 - Facebook
- javascript - 从 JS 中的现有数组中创建一个具有相应总数的对象数组
- git - Git Reset master / 将代码从分支复制到 master
- reactjs - 反应钩子没有设置状态
- sql - 在不丢失任何信息的情况下连接表