假设我正在使用Swift并在框架中调用期望委托的方法。
是否有可能提供一个闭包并在那里内联实现委托?
我希望能够像Java中的匿名类一样使用它。例如:
let cnx:NSURLConnection = NSURLConnection(request: request, delegate: {
func connection(connection: NSURLConnection!, didReceiveData data: NSData!){
//append data
}
func connectionDidFinishLoading(connection: NSURLConnection){
//all done
}
});
答案 0 :(得分:20)
您无法定义匿名类,但您可以定义一个非常相似的本地类。我实际上已经从内联类方法迁移出来,因为REPL似乎有问题,尽管编译器看起来很好。我现在使用的方法是定义一个胶水类,它将方法转发到init中定义的闭包,所以感觉非常自然。
URLConnectionDataDelegate定义为:
class GreenUrlConnectionDataDelegate: NSObject, NSURLConnectionDataDelegate {
var didFinishLoading:()->()
var didReceiveResponse:((NSURLResponse!)->())?
var didReceiveData:((NSData!)->())?
var didFailWithError:((NSError!)->())?
func connectionDidFinishLoading(conn:NSURLConnection!) {
didFinishLoading()
}
func connection(conn:NSURLConnection!, didReceiveResponse response:NSURLResponse!) {
didReceiveResponse?(response)
}
func connection(conn:NSURLConnection!, didReceiveData data:NSData!) {
didReceiveData?(data)
}
func connection(conn:NSURLConnection!, didFailWithError error:NSError!) {
didFailWithError?(error)
}
init(
didFinishLoading:()->(),
didReceiveResponse:((NSURLResponse!)->())? = nil,
didReceiveData:((NSData!)->())? = nil,
didFailWithError:((NSError!)->())? = nil
) {
self.didFinishLoading = didFinishLoading
self.didReceiveResponse = didReceiveResponse
self.didReceiveData = didReceiveData
self.didFailWithError = didFailWithError
}
}
这允许我使用内联委托定义一个函数:
func downloadUrl(string:String, completion:(data:NSData?, error:NSError?) -> ()) {
let url = NSURL(string:string)
let request = NSURLRequest(URL: url)
var received:NSMutableData! = nil
let conn = NSURLConnection(request: request, delegate: GreenUrlConnectionDataDelegate(
didFinishLoading:{
completion(data:received, error:nil)
},
didReceiveResponse:{
if let capacity = $0?.expectedContentLength {
if capacity > 0 {
received = NSMutableData(capacity: Int(capacity))
}
else {
received = NSMutableData()
}
}
},
didReceiveData:{
if $0 != nil {
received.appendData($0)
}
},
didFailWithError:{
completion(data:nil, error:$0)
}
)
)
}
在操场上测试它的代码:
downloadUrl("http://www.google.com") {
(data:NSData?, error:NSError?) -> () in
println("completion")
println("data.size: \(data?.length)")
println("error: \(error?.localizedDescription)")
}
XCPSetExecutionShouldContinueIndefinitely()
你可以想象甚至可以将胶水类嵌入到需要代表的班级的扩展中,尽管我还没有尝试过。
答案 1 :(得分:0)
闭包与匿名类不同,所以不,我认为你不会找到一个能达到你想要的模式。您使用与JavaScript或C#类似的样式来创建对象实例。这不是Swift。
已经有了在不创建类实例的情况下实现委托的技术。例如,参见ReactiveCocoa'delegate pattern'。