5

I'm using NSMapTable in a number of places in an iOS 6 project, and would like to be able to use the new dictionary subscripting style for accessing objects. (NSMapTable behaves mostly like an NSMutableDictionary, but can be configured with various memory management options for the keys and values it stores. More background in this StackOverflow question.)

The compiler reports this when attempting to use subscripting syntax on an NSMapTable instance:

Expected method to read dictionary element not found on object of type 'NSMapTable *'.

How can I use a category to extend NSMapTable to allow the new NSDictionary-style subscripting?

Community
  • 1
  • 1
mjh
  • 3,508
  • 3
  • 19
  • 19

2 Answers2

5

The answer's actually simple; see this question for more information about how subscripting is implemented. Add a category like this.

Header:

@interface NSMapTable (Subscripting)

- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key;
- (id)objectForKeyedSubscript:(id)key;

@end

Implementation:

@implementation NSMapTable (Subscripting)

- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key {
    [self setObject:obj forKey:key];
}

- (id)objectForKeyedSubscript:(id)key {
    return [self objectForKey:key];
}

@end

This makes me wonder, for a moment, whether subscript access is actually a tiny bit slower than the alternative in some or all cases, but the words "premature optimization" make that thought inconsequential.

Community
  • 1
  • 1
mjh
  • 3,508
  • 3
  • 19
  • 19
  • 1
    IMO, this is not a good idea. `NSMapTable` doesn't have subscripting for a reason. For example, if you've got a `NSMapTable` using `NSPointerFunctionsStrongMemory`, why would you need to conform to `NSCopying`? This category actually cripples `NSMapTable` to a dictionary-like collection. – Rudolf Adamkovič Apr 22 '13 at 08:16
  • 2
    @RudolfAdamkovic you can avoid usage of `NSCopying` in the subscription methods declarations. – k06a Feb 17 '17 at 13:35
  • One of the advantages of the `NSMapTable` is that it *does not* require the objects to conform to the `NSCopying` protocol. So it makes no sense to add it to the category implementation. – tomacco May 04 '18 at 15:53
2

Improved @mjh answer with NSDictionary's behavior on setting object for nil key and added Obj-C Generics:

@interface NSMapTable<KeyType, ObjectType> (Subscripting)

- (void)setObject:(ObjectType)obj forKeyedSubscript:(KeyType)key;
- (ObjectType)objectForKeyedSubscript:(KeyType)key;

@end

@implementation NSMapTable (Subscripting)

- (void)setObject:(id)obj forKeyedSubscript:(id)key {
    if (object) {
        [self setObject:obj forKey:key];
    } else {
        [self removeObjectForKey:key];
    }
}

- (id)objectForKeyedSubscript:(id)key {
    return [self objectForKey:key];
}

@end
k06a
  • 17,755
  • 10
  • 70
  • 110