Swift:委托/事件来自 C# 背景
Swift: Delegates / Events coming from C# background
我有一个业务逻辑 class,在进行简单的 Web 服务调用后 returns 一个对象。点击按钮时调用它(在我的视图控制器中)。对我的业务逻辑 class 的调用可能需要几秒钟才能运行,我不想阻塞主线程。
如何在我的 ViewController 可以订阅的业务逻辑 class 中引发事件,以便我知道是时候处理和显示该对象了?
对于这种特殊情况,您可能需要关闭:
class BusinessClass {
func someExpensiveOperationWithCompletion(completion: (someArg: AnyObject) -> ()) {
// Do expensive stuff in background
completion(someArg: "Pass back info here")
}
}
然后,这样称呼它:
let business = BusinessClass()
business.someExpensiveOperationWithCompletion { (someArg) -> () in
println("Finished w/ \(someArg)")
}
不同的平台做事不同。如果你在想
How do I raise an event in my BL class that my ViewController can subscribe to ... ?
您将与框架作斗争,并且会遇到困难和过于复杂的代码。
相反,您应该问的更多是
How do I know when an asynchronous operation has completed?
对于 Cocoa,该问题的答案是您可以使用在操作完成时调用的完成 block/closure,或者使用调用方法的委托回调操作完成后在委托上。 (还有更多选择,但这是最常见的两个)。
中找到有关何时使用不同通信机制的有用读物
闭包
Cocoa 中的常见设计是将闭包作为异步操作的最后一个参数,在操作完成时调用闭包并将数据作为参数传递到闭包中。如果操作失败,通常还有第二个参数用于可选错误(并使成功数据也可选)
例如下面的例子(为了清楚起见,我为闭包定义了一个类型别名):
typealias FooCompletion = (data: FooData?, error: NSError?) -> ()
func doSomething(completion: FooCompletion) {
// do asyncrounous work
let successful: Bool = // based on the operation's success
if successful {
completion(data: someValidData, error: nil)
} else {
let error = NSError() // fill with information about the error
completion(data: nil, error: error)
}
}
你可以使用这样的方法,像这样(这里有一个尾随闭包):
yourBusinessLogic.doSomething { data, error in // FooData?, NSError?
if let validData = data {
// it completed (and validData now holds the data from the operation)
} else {
// there was an error that should be handled
}
}
代表
另一种替代方法,即多年来在 Cocoa 中采用的方法,是定义一个委托协议,并为 class 中的可选委托提供一个 属性 来执行异步任务。如果操作既可以成功也可以失败,这两种情况都有委托方法是很常见的:
protocol BusinessLogicDelegate {
func somethingDidFinish(data: FooData)
func somethingDidFail(error: NSError)
}
class BusinessLogic {
var delegate: BusinessLogicDelegate? // optional delegate
// ...
}
然后在完成可选任务时,将其中一个回调发送给委托(如果有的话)
func doSomething() {
// do asyncrounous work
let successful: Bool = // based on the operation's success
if successful {
delegate?.somethingDidFinish(someValidData)
} else {
let error = NSError() // fill with information about the error
delegate?.somethingDidFail(error)
}
}
在这种情况下,您可以将委托分配给业务逻辑实例,调用异步方法并等待回调之一:
yourBusinessLogic.delegate = yourDelegate // doesn't have to be set every time
yourBusinessLogic.doSomething()
// later on, one of the callbacks is called on the delegate
我有一个业务逻辑 class,在进行简单的 Web 服务调用后 returns 一个对象。点击按钮时调用它(在我的视图控制器中)。对我的业务逻辑 class 的调用可能需要几秒钟才能运行,我不想阻塞主线程。
如何在我的 ViewController 可以订阅的业务逻辑 class 中引发事件,以便我知道是时候处理和显示该对象了?
对于这种特殊情况,您可能需要关闭:
class BusinessClass {
func someExpensiveOperationWithCompletion(completion: (someArg: AnyObject) -> ()) {
// Do expensive stuff in background
completion(someArg: "Pass back info here")
}
}
然后,这样称呼它:
let business = BusinessClass()
business.someExpensiveOperationWithCompletion { (someArg) -> () in
println("Finished w/ \(someArg)")
}
不同的平台做事不同。如果你在想
How do I raise an event in my BL class that my ViewController can subscribe to ... ?
您将与框架作斗争,并且会遇到困难和过于复杂的代码。
相反,您应该问的更多是
How do I know when an asynchronous operation has completed?
对于 Cocoa,该问题的答案是您可以使用在操作完成时调用的完成 block/closure,或者使用调用方法的委托回调操作完成后在委托上。 (还有更多选择,但这是最常见的两个)。
中找到有关何时使用不同通信机制的有用读物闭包
Cocoa 中的常见设计是将闭包作为异步操作的最后一个参数,在操作完成时调用闭包并将数据作为参数传递到闭包中。如果操作失败,通常还有第二个参数用于可选错误(并使成功数据也可选)
例如下面的例子(为了清楚起见,我为闭包定义了一个类型别名):
typealias FooCompletion = (data: FooData?, error: NSError?) -> ()
func doSomething(completion: FooCompletion) {
// do asyncrounous work
let successful: Bool = // based on the operation's success
if successful {
completion(data: someValidData, error: nil)
} else {
let error = NSError() // fill with information about the error
completion(data: nil, error: error)
}
}
你可以使用这样的方法,像这样(这里有一个尾随闭包):
yourBusinessLogic.doSomething { data, error in // FooData?, NSError?
if let validData = data {
// it completed (and validData now holds the data from the operation)
} else {
// there was an error that should be handled
}
}
代表
另一种替代方法,即多年来在 Cocoa 中采用的方法,是定义一个委托协议,并为 class 中的可选委托提供一个 属性 来执行异步任务。如果操作既可以成功也可以失败,这两种情况都有委托方法是很常见的:
protocol BusinessLogicDelegate {
func somethingDidFinish(data: FooData)
func somethingDidFail(error: NSError)
}
class BusinessLogic {
var delegate: BusinessLogicDelegate? // optional delegate
// ...
}
然后在完成可选任务时,将其中一个回调发送给委托(如果有的话)
func doSomething() {
// do asyncrounous work
let successful: Bool = // based on the operation's success
if successful {
delegate?.somethingDidFinish(someValidData)
} else {
let error = NSError() // fill with information about the error
delegate?.somethingDidFail(error)
}
}
在这种情况下,您可以将委托分配给业务逻辑实例,调用异步方法并等待回调之一:
yourBusinessLogic.delegate = yourDelegate // doesn't have to be set every time
yourBusinessLogic.doSomething()
// later on, one of the callbacks is called on the delegate