我有一个Business Logic类,它在进行简单的Web服务调用后返回一个对象。点击按钮时(在我的视图控制器中)调用它。这个对我的Business Logic类的调用可能需要几秒钟才能运行,我不想阻止主线程。
如何在我的View Logic类可以订阅的Business Logic类中引发一个事件,以便我知道是时候处理和显示该对象了?
答案 0 :(得分:5)
不同的平台以不同的方式做事。如果你在想
如何在BLCon类中引发一个我的ViewController可以订阅的事件......?
你将要与框架作斗争,并为它提供困难时间和过于复杂的代码。
相反,你应该问的是更多的
我如何知道异步操作何时完成?
对于Cocoa来说,这个问题的答案是你可以使用在操作完成时调用的完成块/闭包,或者在操作完成时使用在委托上调用的方法的委托回调。 (还有更多的选择,但这两种是最常见的)。
有关何时使用不同通信机制的有用说明可在this objc.io article
中找到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中完成多年的方式,是定义一个委托协议,并为执行异步任务的类中的可选委托提供一个属性。如果操作既可以成功又可以失败,那么两种情况都有委托方法:
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
答案 1 :(得分:1)
对于这种特殊情况,您可能需要一个闭包:
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)")
}
答案 2 :(得分:-1)
您可以通过接受回调函数作为Business Logic类上方法的参数来实现所需的行为。如果您需要在课堂上执行异步代码的进一步说明,我建议您查阅Grand Central Dispatch文档。
业务逻辑类的示例可能如下所示:
class BusinessLogic {
func doSomething(callback : () -> Void) {
// long running operation
callback() // call when done with operation
}
}
您可以通过将函数传递给doSomething方法从视图控制器中调用它:
let bl = BusinessLogic()
bl.doSomething({
// execute callback statements
})