Swift:来自C#背景的代表/活动

时间:2015-01-05 16:33:06

标签: ios swift

我有一个Business Logic类,它在进行简单的Web服务调用后返回一个对象。点击按钮时(在我的视图控制器中)调用它。这个对我的Business Logic类的调用可能需要几秒钟才能运行,我不想阻止主线程。

如何在我的View Logic类可以订阅的Business Logic类中引发一个事件,以便我知道是时候处理和显示该对象了?

3 个答案:

答案 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 
})