Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subscripting syntax for NSMapTable in iOS 6

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?

like image 222
mjh Avatar asked Oct 31 '12 00:10

mjh


People also ask

What is the difference between NSMapTable vs NSDictionary?

NSDictionary / NSMutableDictionary copies keys, and holds strong references to values. NSMapTable is mutable, without an immutable counterpart. NSMapTable can hold keys and values with weak references, in such a way that entries are removed when either the key or value is deallocated.

What is NSMapTable?

A collection similar to a dictionary, but with a broader range of available memory semantics. iOS 6.0+ iPadOS 6.0+ macOS 10.5+ Mac Catalyst 13.1+ tvOS 9.0+ watchOS 2.0+

How do I create an NSDictionary in Objective C?

Creating NSDictionary Objects Using Dictionary Literals In addition to the provided initializers, such as init(objects:forKeys:) , you can create an NSDictionary object using a dictionary literal. In Objective-C, the compiler generates code that makes an underlying call to the init(objects:forKeys:count:) method.

What is NSMutableDictionary?

An object representing a dynamic collection of key-value pairs, for use instead of a Dictionary variable in cases that require reference semantics.


2 Answers

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.

like image 154
mjh Avatar answered Sep 19 '22 05:09

mjh


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
like image 28
k06a Avatar answered Sep 19 '22 05:09

k06a