I'm trying to use an Objective-C library which expects a NSDictionary
as its return type. Within the NSDictionary
, I can return values of any type, including blocks.
I cannot figure out if there is a way to write an analogous swift method that returns a Dictionary with a closure or a string as a possible value type.
I can't use AnyObject
as the value type for the dictionary so this doesn't work:
Dictionary<String,AnyObject> = ["Key":{(value:AnyObject) -> String in return value.description]
I get a Does not conform to protocol error
from the compiler regarding the closure and AnyObject
.
Is there a higher level type or protocol that both closures and basic types adhere to that I can use as the value type in a Dictionary?
If you still need a workaround, here is one; usage looks like this:
Output is:
The
Blocks
class is defined like this in Objective-C (with corresponding header and bridging header, I won't put those here):You also need to add a new
xyzBlockToId
andtoXyzBlock
method for every new closure-type you want to use. It's pretty ugly, but it works.Could you use an
NSMutableDictionary
?Alternatively, this seemed to work for me using your example:
Hmm, maybe this Swift-Code doesn't really help, because you want to have heterogenous dictionaries.
It's also not possible to put closures into an
NSDictionary
, it seems (as a closure does not conform toAnyObject
).Your basic problem is that in Objective-C closures (aka blocks) are represented as NSObject (or more precisely are transparently converted to NSObjects) while in Swift there is no such mapping. This means that closures can not be directly stored in a Dictionary (short of using objective-c glue)
The closest I can come up with is something along the lines of wrapping the value in an enum:
Which is probably a better solution anyway, because this way you have an explicit typing associated with individual arguments instead of it being implicit using some sort of inflection.
Alternatively, you could only wrap the closure and use a dictionary of type
Dictionary<String,Any>
.There is another type,
Any
, that object, structs and primitives all conform to but functions do not. There is no general function type, but you can describe a function type as its arguments and return value like this:Function Types
A more "generic" solution which should work with
Any
object, but shown with closures and function references. Drop it into a playground and try it out!You could also roll your own higher type using an
enum
. You need the dictionary values to be either strings or functions which return strings, so define a type to represent that:Then, you can put it in a dictionary:
Then you'll need to process the dictionary values using pattern matching: