删除 KVC 生成的 NSMutableArray 中的 NSNull 值
Remove NSNull values in a KVC generated NSMutableArray
这里有一个小测试:
NSDictionary * test = @ { @"centers" : @[
@{ @"id":@"12345", @"favorite":@NO },
@{ @"id":@"2345", @"favorite":@NO },
@{ @"id":@"345", @"favorite":@YES },
@{ @"favorite":@NO }
]};
NSMutableArray * test2 = [test mutableArrayValueForKeyPath:@"centers.id"];
NSLog(@"%@",test2);
日志给出:
(
12345,
2345,
345,
"<null>"
)
太好了,现在,我希望摆脱 NSNull 值...根据 How will I be able to remove [NSNull Null] objects from NSMutableArray? 这是方法:
[test2 removeObjectIdenticalTo:[NSNull null]];
NSLog(@"%@",test2);
不幸的是,它崩溃了:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSDictionaryI 0x7fe2ee01e970> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key id.'
*** First throw call stack:
(
0 CoreFoundation 0x000000010e47df35 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010e116bb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010e47db79 -[NSException raise] + 9
3 Foundation 0x000000010dcb37b3 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 259
4 Foundation 0x000000010dd44be0 -[NSArray(NSKeyValueCoding) setValue:forKey:] + 186
5 Foundation 0x000000010dd471cc -[NSKeyValueSlowMutableArray removeObjectAtIndex:] + 89
6 CoreFoundation 0x000000010e3d75a3 -[NSMutableArray removeObjectIdenticalTo:] + 131
7 TestImageSizeReduction 0x000000010dbe6d35 -[ViewController viewDidLoad] + 1397
8 UIKit 0x000000010ebd2a90 -[UIViewController loadViewIfRequired] + 738
9 UIKit 0x000000010ebd2c8e -[UIViewController view] + 27
10 UIKit 0x000000010eaf1ca9 -[UIWindow addRootViewControllerViewIfPossible] + 58
11 UIKit 0x000000010eaf2041 -[UIWindow _setHidden:forced:] + 247
12 UIKit 0x000000010eafe72c -[UIWindow makeKeyAndVisible] + 42
13 UIKit 0x000000010eaa9061 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2628
14 UIKit 0x000000010eaabd2c -[UIApplication _runWithMainScene:transitionContext:completion:] + 1350
15 UIKit 0x000000010eaaabf2 -[UIApplication workspaceDidEndTransaction:] + 179
16 FrontBoardServices 0x0000000111f582a3 __31-[FBSSerialQueue performAsync:]_block_invoke + 16
17 CoreFoundation 0x000000010e3b353c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
18 CoreFoundation 0x000000010e3a9285 __CFRunLoopDoBlocks + 341
19 CoreFoundation 0x000000010e3a9045 __CFRunLoopRun + 2389
20 CoreFoundation 0x000000010e3a8486 CFRunLoopRunSpecific + 470
21 UIKit 0x000000010eaaa669 -[UIApplication _run] + 413
22 UIKit 0x000000010eaad420 UIApplicationMain + 1282
23 TestImageSizeReduction 0x000000010dbe81f3 main + 115
24 libdyld.dylib 0x0000000110c50145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
所以,我知道很多从数组中删除 NSNull
实例的方法(谓词、indexesPassingTests 等),但我真的很想知道为什么这会失败,解释这么少。
提前致谢。
编辑:
为了防止 Ian 的回答中给出的代理问题,最简单的解决方案是:
NSMutableArray * test2 = [[test valueForKeyPath:@"centers.id"] mutableCopy];
从 mutableArrayValueForKeyPath
返回的 NSMutableArray
不是值的副本,而是在每次访问时查找原始对象的代理可变数组。
告诉它删除对象将作用于您的原始对象。告诉它删除 centers.id
为 [NSNull null]
的对象会导致失败,因为这些对象不响应 id
的键值映射。奇怪的是,它一开始会给你任何结果,但你不能以你想要的方式使用这个 [NSNull null]
结果。
如果您只想要值而不想要任何可用于修改原始对象的操作,我建议您以不同的方式开始构建数组;也许有一个谓词。
NSNull 是一个 null 对象类型,它允许将 NULL 对象添加到数组,因为数组不接受 nil 值作为输入。如果任何东西为 NULL,我们必须将其输入数组,我们使用 [NSNull null] 单例类型对象。
在您的情况下,由于内存位置为空而生成,它不是 [NSNull null] 对象类型。您不能使用 [test2 removeObjectIdenticalTo:[NSNull null]];
删除它
可以使用 NSPredicate 搜索删除它
试试这个使用 NSPredicate 搜索来过滤 NSArray。您可以使用 NSPredicate
删除 null
NSDictionary * test = @ { @"centers" : @[
@{ @"id":@"12345", @"favorite":@NO },
@{ @"id":@"2345", @"favorite":@NO },
@{ @"id":@"345", @"favorite":@YES },
@{ @"favorite":@NO }
]};
NSMutableArray * test2 = [test mutableArrayValueForKeyPath:@"centers.id"];
NSLog(@"%@",test2);
NSPredicate *predicate=[NSPredicate predicateWithFormat:@"SELF!=nil"];
NSArray *test3=[test2 filteredArrayUsingPredicate:predicate];
NSLog(@"%@",test3);
这里有一个小测试:
NSDictionary * test = @ { @"centers" : @[
@{ @"id":@"12345", @"favorite":@NO },
@{ @"id":@"2345", @"favorite":@NO },
@{ @"id":@"345", @"favorite":@YES },
@{ @"favorite":@NO }
]};
NSMutableArray * test2 = [test mutableArrayValueForKeyPath:@"centers.id"];
NSLog(@"%@",test2);
日志给出:
(
12345,
2345,
345,
"<null>"
)
太好了,现在,我希望摆脱 NSNull 值...根据 How will I be able to remove [NSNull Null] objects from NSMutableArray? 这是方法:
[test2 removeObjectIdenticalTo:[NSNull null]];
NSLog(@"%@",test2);
不幸的是,它崩溃了:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSDictionaryI 0x7fe2ee01e970> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key id.'
*** First throw call stack:
(
0 CoreFoundation 0x000000010e47df35 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010e116bb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010e47db79 -[NSException raise] + 9
3 Foundation 0x000000010dcb37b3 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 259
4 Foundation 0x000000010dd44be0 -[NSArray(NSKeyValueCoding) setValue:forKey:] + 186
5 Foundation 0x000000010dd471cc -[NSKeyValueSlowMutableArray removeObjectAtIndex:] + 89
6 CoreFoundation 0x000000010e3d75a3 -[NSMutableArray removeObjectIdenticalTo:] + 131
7 TestImageSizeReduction 0x000000010dbe6d35 -[ViewController viewDidLoad] + 1397
8 UIKit 0x000000010ebd2a90 -[UIViewController loadViewIfRequired] + 738
9 UIKit 0x000000010ebd2c8e -[UIViewController view] + 27
10 UIKit 0x000000010eaf1ca9 -[UIWindow addRootViewControllerViewIfPossible] + 58
11 UIKit 0x000000010eaf2041 -[UIWindow _setHidden:forced:] + 247
12 UIKit 0x000000010eafe72c -[UIWindow makeKeyAndVisible] + 42
13 UIKit 0x000000010eaa9061 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2628
14 UIKit 0x000000010eaabd2c -[UIApplication _runWithMainScene:transitionContext:completion:] + 1350
15 UIKit 0x000000010eaaabf2 -[UIApplication workspaceDidEndTransaction:] + 179
16 FrontBoardServices 0x0000000111f582a3 __31-[FBSSerialQueue performAsync:]_block_invoke + 16
17 CoreFoundation 0x000000010e3b353c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
18 CoreFoundation 0x000000010e3a9285 __CFRunLoopDoBlocks + 341
19 CoreFoundation 0x000000010e3a9045 __CFRunLoopRun + 2389
20 CoreFoundation 0x000000010e3a8486 CFRunLoopRunSpecific + 470
21 UIKit 0x000000010eaaa669 -[UIApplication _run] + 413
22 UIKit 0x000000010eaad420 UIApplicationMain + 1282
23 TestImageSizeReduction 0x000000010dbe81f3 main + 115
24 libdyld.dylib 0x0000000110c50145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
所以,我知道很多从数组中删除 NSNull
实例的方法(谓词、indexesPassingTests 等),但我真的很想知道为什么这会失败,解释这么少。
提前致谢。
编辑: 为了防止 Ian 的回答中给出的代理问题,最简单的解决方案是:
NSMutableArray * test2 = [[test valueForKeyPath:@"centers.id"] mutableCopy];
从 mutableArrayValueForKeyPath
返回的 NSMutableArray
不是值的副本,而是在每次访问时查找原始对象的代理可变数组。
告诉它删除对象将作用于您的原始对象。告诉它删除 centers.id
为 [NSNull null]
的对象会导致失败,因为这些对象不响应 id
的键值映射。奇怪的是,它一开始会给你任何结果,但你不能以你想要的方式使用这个 [NSNull null]
结果。
如果您只想要值而不想要任何可用于修改原始对象的操作,我建议您以不同的方式开始构建数组;也许有一个谓词。
NSNull 是一个 null 对象类型,它允许将 NULL 对象添加到数组,因为数组不接受 nil 值作为输入。如果任何东西为 NULL,我们必须将其输入数组,我们使用 [NSNull null] 单例类型对象。 在您的情况下,由于内存位置为空而生成,它不是 [NSNull null] 对象类型。您不能使用 [test2 removeObjectIdenticalTo:[NSNull null]];
删除它可以使用 NSPredicate 搜索删除它
试试这个使用 NSPredicate 搜索来过滤 NSArray。您可以使用 NSPredicate
删除 nullNSDictionary * test = @ { @"centers" : @[
@{ @"id":@"12345", @"favorite":@NO },
@{ @"id":@"2345", @"favorite":@NO },
@{ @"id":@"345", @"favorite":@YES },
@{ @"favorite":@NO }
]};
NSMutableArray * test2 = [test mutableArrayValueForKeyPath:@"centers.id"];
NSLog(@"%@",test2);
NSPredicate *predicate=[NSPredicate predicateWithFormat:@"SELF!=nil"];
NSArray *test3=[test2 filteredArrayUsingPredicate:predicate];
NSLog(@"%@",test3);