Storing a dispatch_source_t in an NSMutableDictionary

171 views Asked by At

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.

2

There are 2 answers

0
CRD On BEST ANSWER

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.

0
James Bucanek On

If you just want to use dispatch source object reference as a key into a dictionary, and you know that all of the objects used as keys exist and are valid (this is an important requirement), then you could just use the pointer value as an integer key:

sources[ @( (intptr_t)source ) ] = @{stuff};

That's because objects don't move once created, so the integer representation of the object reference will be a constant for the lifetime of that object. Just make sure you remove the entry before destroying the object or you could end up with duplicate keys.