iOS — distinguish an NSDictionary from an NSMutableDictionary?

后端 未结 6 1125
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-21 14:34

I have the following code fragment:

NSString* value = @\"value\";
NSString* key = @\"key\";
NSMutableDictionary* foo = [NSMutableDictionary dictionary];
NSDictio         


        
相关标签:
6条回答
  • 2021-01-21 14:44

    If you really don't care if it's mutable, but want to mutate it anyway, you could try this:

    NSString* value = @"value";
    NSString* key = @"key";
    
    NSDictionary* bar = [NSDictionary dictionary];
    NSLog(@"bar desc: %@", [bar description]);
    NSMutableDictionary* temp = [bar mutableCopy];
    [temp setValue:value forKey:key];
    bar = temp;
    NSLog(@"bar desc: %@", [bar description]);
    
    0 讨论(0)
  • 2021-01-21 14:52

    If you need to guarantee that a dictionary is mutable, you should:

    • create it as mutable if you are the one initializing it
    • turn it into a mutable instance with the -[NSDictionary mutableCopy] method, for example if you're calling an API that returns an NSDictionary. Note that mutableCopy increments the retain count; you need to release this instance if you are using manual reference counting.

    Determining whether an NSDictionary is mutable before attempting to modify its keys and/or values can be considered an example of a code smell, indicating that there's a deeper problem that should be solved. In other words, you should always know whether a given dictionary instance is NSDictionary or NSMutableDictionary. The code should be clear on that point.

    0 讨论(0)
  • 2021-01-21 14:56

    Honestly, you can't easily tell the difference without a @try block. Standard practice is as follows:

    • If you want to check whether it's mutable in order to avoid someone passing you an unexpectedly mutable object and then mutating it out from under you, copy the dictionary. If it's really non-mutable, the frameworks will optimize that into a retain. If it really was mutable, then you probably wanted a copy anyway.
    • If you need a mutable dictionary, declare your method parameters to require one. Simple as that.
    • In general, trust that people won't try to mutate objects unless specifically told they were mutable.
    0 讨论(0)
  • 2021-01-21 15:04

    It's pretty simple actually, all you need to do is test against the member of the class, like this:

    if ([bar isMemberOfClass:[NSMutableDictionary class]]){
        [bar setValue:value forKey: key];
    }
    

    iPhone SDK difference between isKindOfClass and isMemberOfClass

    0 讨论(0)
  • 2021-01-21 15:09
    NSAssert([bar isMemberOfClass: [NSMutableDictionary class]], @"");
    
    0 讨论(0)
  • 2021-01-21 15:09

    I end up using @try catch but it only fires once. So it works like this

    NSMutableDictionary *valuesByIdMutable = (id)self.valuesById;
    
    simplest_block block = ^{
        [valuesByIdMutable setObject:obj forKey:key];
    };
    
    @try {
        block();
    } @catch (NSException *exception) {
        self.valuesById = valuesByIdMutable = [valuesByIdMutable mutableCopy];
        block();
    }
    
    0 讨论(0)
提交回复
热议问题