Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift - Store Closures in Dictionary

Is it possible to store closures in dictionaries (how we could store ObjC blocks in dictionaries)? Example:

   data = [String:AnyObject]()
   data!["so:c0.onSelection"] = {() in
       Debug.log(.Debug, message: "Hello, World!")
   }
like image 555
Stephen Donnell Avatar asked Aug 05 '14 01:08

Stephen Donnell


People also ask

How many types of closures are there in Swift?

As shown in the above table, there are three types of closures in Swift, namely global functions, nested functions, and closure expressions. They differ in several aspects, including their use scopes, their names, and whether they capture values, which will be discussed more in a later section.

What are the closures in Swift?

Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages. Closures can capture and store references to any constants and variables from the context in which they're defined. This is known as closing over those constants and variables.

How do you declare a closure in Swift?

Swift Closure Declarationparameters - any value passed to closure. returnType - specifies the type of value returned by the closure. in (optional) - used to separate parameters/returnType from closure body.

How do you read Swift closures?

Understanding closure syntax in Swift For closures, we must always write down the return type even when the closure doesn't return anything. Instead of -> Void or "returns Void ", this type specifies -> () or "returns empty tuple". In Swift, Void is a type alias for an empty tuple.


2 Answers

You can, but with some restrictions. First of all, function types don't inherit from AnyObject and don't share a common base class. You can have a dictionary [String: () -> Void] and [String: (String) -> Int], but they can't be stored in the same dictionary.

I also had to use a typealias to define the dictionary so that swift would parse correctly. Here's an example based off of your snippet.

typealias myClosure = () -> Void
var data: [String: myClosure]? = [String: myClosure]()
data!["so:c0.onSelection"] = {() -> Void in
    Debug.log(.Debug, message: "Hello, World!")
}
like image 113
Connor Avatar answered Sep 22 '22 00:09

Connor


I have a different approach

I create a "holder" class to hold your closures something like this:

typealias SocialDownloadImageClosure = (image : UIImage?, error: NSError?) -> ()
typealias SocialDownloadInformationClosure = (userInfo : NSDictionary?, error: NSError?) -> ()


private class ClosureHolder
{
 let imageClosure:SocialDownloadImageClosure?
 let infoClosure:SocialDownloadInformationClosure?

 init(infoClosure:SocialDownloadInformationClosure)
 {
    self.infoClosure = infoClosure
 }
 init(imageClosure:SocialDownloadImageClosure)
 {
    self.imageClosure = imageClosure
 }
}

then i make the dictionary like this:

var requests = Dictionary<String,ClosureHolder>()

Now to add a closure to the dictionary just do this:

self.requests["so:c0.onSelection"] = ClosureHolder(completionHandler)
like image 44
João Nunes Avatar answered Sep 23 '22 00:09

João Nunes