Reputation: 696
I have an application which talks to a device over a BLE UART connection. When data is received, a didReceiveData() delegate is called. Here I need determine who called the data and trigger the corresponding method (of another delegate). I was planning on creating a connections dictionary keyed by a connectionID string created when the connection is established, along with a selector to the callback (may not always be supplied).
class Connection: NSObject {
var selectr: Selector
var dataString: String?
init(selectR:Selector,dString:String) {
selectr = selectR
dataString = dString
}
}
connections[String:Connection]()
func sendData(dataString:String,callbackSelector:Selector){
con = Connection(selectR: callbackSelector, dString:"")
connections[cid] = con
}
... When calling:
let sel = Selector(anotherDelegate?.didReceiveLocation(""))
self.sendData("sendMe",Selector(anotherDelegate?.didReceiveLocation))
I get a few errors doing this, first a Type NSData does not conform to protocol StringLiteralConvertible. NSData referring to the argument of didReceiveLocation. The second is on the self.sendData line: Cannot invoke 'init' with an argument list of type (StringLiteralConvertible,Selector).
Does this approach make sense? How can I store the callback method of another delegate in a dictionary or other struct to make it accessible from the didReceiveData delegate method?
Upvotes: 1
Views: 1795
Reputation: 41236
Selectors are so Objective-C... why not just use a closure?
To declare a dictionary with String as keys and functions that take a String as a parameter and return nothing:
connections = [String:String->()]()
To declare a function that takes a closure with a single String argument and no return value, use something like:
func sendData(dataString:String, callback:String->()) {
...
connections[cid] = callback
...
}
To invoke that closure later, you can call it as a subroutine (in this case after performing a dictionary lookup, using optional chaining in case it hasn't been assigned yet):
func didReceiveData(...) {
...
connections[cid]?(response)
}
Then to call the sendData routine declared above and pass in a closure using one of the several abbreviated syntaxes:
self.sendData("sendMe") { response in
...
}
Note that this is actually short-hand for:
self.sendData("sendMe", callback:{ response:String in
...
})
Note that this mechanism can also be used by an Objective-C caller, since closures map more or less directly to Objective-C blocks.
For more information on closures, their definition and invocation, I'd strongly recommend downloading the free Swift book from the iTunes book store.
Upvotes: 1