问题
I've got a layered NSMutableDictionary object and i'd like to be able to remove dictionaries deeper down in the hierarchy. Is there a quick and easy way to do this, for example, a removeObjectAtKeyPath-like method? Can't seem to find one.
Thanks!
回答1:
Nothing built in, but your basic category method will do just fine:
@implementation NSMutableDictionary (WSSNestedMutableDictionaries)
- (void)WSSRemoveObjectForKeyPath: (NSString *)keyPath
{
// Separate the key path
NSArray * keyPathElements = [keyPath componentsSeparatedByString:@"."];
// Drop the last element and rejoin the path
NSUInteger numElements = [keyPathElements count];
NSString * keyPathHead = [[keyPathElements subarrayWithRange:(NSRange){0, numElements - 1}] componentsJoinedByString:@"."];
// Get the mutable dictionary represented by the path minus that last element
NSMutableDictionary * tailContainer = [self valueForKeyPath:keyPathHead];
// Remove the object represented by the last element
[tailContainer removeObjectForKey:[keyPathElements lastObject]];
}
@end
N.B. That this requires that the second-to-last element of the path -- the tailContainer
be something that responds to removeObjectForKey:
, probably another NSMutableDictionary
. If it's not, boom!
回答2:
You can create a category :
This is upto 1 level down:
#import "NSMutableDictionary+RemoveAtKeyPath.h"
@implementation NSMutableDictionary (RemoveAtKeyPath)
-(void)removeObjectAtKeyPath:(NSString *)keyPath{
NSArray *paths=[keyPath componentsSeparatedByString:@"."];
[[self objectForKey:paths[0]] removeObjectForKey:paths[1]];
}
@end
It is called as :
NSMutableDictionary *adict=[[NSMutableDictionary alloc]initWithDictionary:@{@"key1" : @"obj1", @"key11":@"obj11"}];
NSMutableDictionary *bdict=[[NSMutableDictionary alloc]initWithDictionary:@{@"key2" : adict}];
NSLog(@"%@",bdict);
NSLog(@"%@",[bdict valueForKeyPath:@"key2.key1"]);
[bdict removeObjectAtKeyPath:@"key2.key1"];
NSLog(@"After category : %@",bdict);
回答3:
Minor improvement to Josh's answer, in order to handle keypaths which don't contain a period (i.e. keypaths which are actually keys):
- (void)removeObjectAtKeyPath:(NSString *)keyPath
{
NSArray *keyPathElements = [keyPath componentsSeparatedByString:@"."];
NSUInteger numElements = [keyPathElements count];
if (numElements == 1) {
[self removeObjectForKey:keyPath];
} else {
NSString *keyPathHead = [[keyPathElements subarrayWithRange:(NSRange){0, numElements - 1}] componentsJoinedByString:@"."];
NSMutableDictionary *tailContainer = [self valueForKeyPath:keyPathHead];
[tailContainer removeObjectForKey:[keyPathElements lastObject]];
}
}
回答4:
I know this is an older post, but I needed to find the same solution in Swift 2.0, unable to find a simple answer I came up with this solution:
public extension NSMutableDictionary {
public func removeObjectAtKeyPath(keyPath:String) {
let elements = keyPath.componentsSeparatedByString(".")
let head = elements.first!
if elements.count > 1 {
let tail = elements[1...elements.count-1].joinWithSeparator(".")
if let d = valueForKeyPath(head) as? NSMutableDictionary {
d.removeObjectAtKeyPath(tail)
}
}else{
removeObjectForKey(keyPath)
}
}
}
I've added an extension to NSMutableDictionary
using recursion to step thru the keyPath
来源:https://stackoverflow.com/questions/15105709/nsmutabledictionary-remove-object-at-key-path