macoscocoansdictionarynsvalue

Storing a dispatch_source_t in an NSMutableDictionary


If I try to use a dispatch_source_t as the key in an NSMutableDictionary:

dispatch_source_t               source = dispatch_source_create(stuff...);
NSMutableDictionary             filesAndSources = [NSMutableDictionary dictionary];

filesAndSources[source] = @{stuff goes here};

I get the warning:

Sending 'dispatch_source_t' (aka 'NSObject<OS_dispatch_source> *') to parameter of incompatible type 'id<NSCopying> _Nonnull'

I assume it's because a dispatch_source_t doesn't use the NSCopying protocol. My solution was to stuff the dispatch_source_t into an NSValue:

NSValue*          val = [NSValue valueWithPointer:(__bridge const void* _Nullable)(source)];
filesAndSources[val] = @{stuff};

This quiets the warning, but I'm not sure if that's the right way to pass a dispatch_source_t around.


Solution

  • Take a look at NSMapTable which has finer control of key and value semantics than NS(Mutable)Dictionary.

    Pointer equality, NSMapTableObjectPointerPersonality, can be specified for the keys rather than requiring they conform to NSCopying and provide isEqual: and hash can be specified for the keys; while still using strong references to the values, NSMapTableStrongMemory, creating a table with:

    [NSMapTable mapTableWithKeyOptions: NSMapTableObjectPointerPersonality
                          valueOptions:NSMapTableStrongMemory]
    

    Instance methods are objectForKey: and setObject:forKey: et al, but you don't get the get/set indexing syntax shorthands available with NS(Mutable)Dictionary.