2015-02-16 1 views
1

Вот небольшой тест:Удалить значения NSNull в КВЦ генерироваться 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 и т.д.), но я действительно хочу, чтобы понять, почему это не удается с так мало объяснений.

Заранее спасибо.

Edit: Чтобы предотвратить проблему прокси дал в ответ Иэна самое простое решение:

NSMutableArray * test2 = [[test valueForKeyPath:@"centers.id"] mutableCopy]; 
+0

Это неизменный словарь, поэтому вы не можете изменить то, что хранится в нем. Попробуйте изменить его на NSMutableDictionary и прокрутите все ключи и удалите те, которые равны '[NSNull null]'. – hhanesand

+0

Спасибо за ваш комментарий, но вызов находится в массиве, а не в словаре, не так ли? – Zaphod

+0

Попробуйте мой ответ. Он должен работать. – Shashi3456643

ответ

3

NSMutableArray вернулся из mutableArrayValueForKeyPath не является копией значений, но вместо этого прокси изменчивый массив, выполняет поиск исходного объекта при каждом доступе.

Указывая, что для удаления объектов будет действовать ваш исходный объект. Указание на удаление объектов, centers.id - [NSNull null], вызывает сбой, поскольку эти объекты не отвечают на сопоставление значений ключей для id. Странно думать, что это дало бы вам какой-то результат в первую очередь, но вы не можете использовать этот результат [NSNull null] так, как хотите.

Если вам нужны только значения, и вы не хотите, чтобы какие-либо операции были доступны, чтобы разрешить модификацию исходного объекта, я предлагаю вам начать свой массив с самого начала; возможно, с предикатом.

+0

Спасибо за ваше объяснение! Это объясняет все аккуратно! Большой! – Zaphod

+0

хорошо ответ ...! – Shoaib

1

NSNull - это нулевой тип объекта, который позволяет добавлять объект NULL к массиву, потому что массив не принимает значение nil в качестве входного. Если что-то, как NULL, мы должны кормить в массив, мы используем объект [NSNull null] singleton type. В вашем случае создается из-за пустой памяти, это не тип объекта [NSNull null]. Вы не можете удалить его, используя [test2 removeObjectIdenticalTo: [NSNull null]];

Он может быть удален с помощью NSPredicate Поиск

Попробуйте Использовать NSPredicate поиск для фильтрации NSArray. Вы можете удалить нуль, используя NSPredicate

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); 
+0

Спасибо за ваш ответ, но я хотел понять, почему удаление произошло сбой, а не как предотвратить его, как я уже упоминал в вопросе. Ян дал хорошее объяснение. – Zaphod

+0

Я дал свое объяснение в своем ответе, почему вы не можете удалить [NSNull null] из вашего массива test2 – Shashi3456643

+0

Фактически, объект является экземпляром NSNull (перечисляем массив и регистрируем каждый класс, вы увидите), ответ был дан Ян, и объясняет это. – Zaphod

Смежные вопросы