使用自定义运算符和完成块

时间:2015-09-01 10:48:33

标签: ios swift asynchronous swift2

要简短地讲故事'说我有一个运营商定义:

infix operator <~ {
    associativity left
    precedence 160
}

让我们说我使用这个操作符做两个对象之间的某些工作,所以我已经定义了这样的函数:

func <~ <T: FirstProtocol, U:SecondProtocol>(lhs: T, rhs: U) {
    //async request
}

现在我们无法返回任何内容,因为运算符函数正在执行异步工作,我们也无法使用更多参数来进行闭包。因为异步函数可能会运行几秒钟,所以我需要一个在异步任务完成时运行的回调。问题是你是否可以使用具有异步功能的运算符?我尝试了各种解决方案,但似乎都没有。

完美的解决方案如下所示:

something <~ somethingElse {
    error in
    //async call finished
}

2 个答案:

答案 0 :(得分:1)

如果您愿意设置一些脚手架,您可以完成此任务。没有办法可以开箱即用。

让我们考虑如何在没有操作员的情况下这样做。我们会有一个操作队列,每个完成后我们都会添加下一个操作。并且每个操作都应该在完成后通知队列。

因此,运营商只负责将操作添加到队列中。如果你想要一个更复杂的实现,请查看Swift的任何Promises库。我试图将这个概念的基本工作实现放在一起:

var queue = NSOperationQueue()

infix operator <~ {
    associativity left
    precedence 160
}

struct QueuedOperation
{
    var operation : NSBlockOperation
}


func <~ (first: ()->(), second:()->())->QueuedOperation {

    let operationOne = NSBlockOperation(block: first)
    let operationTwo = NSBlockOperation(block: second)

    operationTwo.addDependency(operationOne)
    queue.addOperation(operationOne)
    queue.addOperation(operationTwo)

    return QueuedOperation(operation: operationTwo)
}

func <~ (first : QueuedOperation, second:()->())->QueuedOperation {

    let operationTwo = NSBlockOperation(block: second)

    operationTwo.addDependency(first.operation)
    queue.addOperation(operationTwo)

    return QueuedOperation(operation: operationTwo)
}



_ = {

    sleep(2)

    print("First")

    } <~ {

        sleep(4)

        print("Second")

    } <~ {

        sleep(8)
        print("Third")
}

所以它的工作原理如下:

操作1&lt;〜操作2&lt;〜操作3

Operation1&lt;〜Operation2

调用第一个将Operation1和&amp;队列上的Operation2并将Operation1添加为Operation2的依赖项。我们从此返回一个QueuedOperation包装Operation2,因为当我们向前链接时,后续的一个依赖于Operation2但是Operation2将再次排队。

返回不同的类型并调度到具有不同类型签名的函数允许我们这样做。

答案 1 :(得分:1)

不幸的是,something <~ somethingElse { err in ... }是不可能的,因为编译器将其解释为something <~ (somethingElse({ err in ... }))

至少,你必须(something <~ somethingElse) { err in ... }。在游乐场试试这个:

import Foundation

infix operator <~ {
associativity left
precedence 160
}

func <~(lhs: Int, rhs: Int) -> ((Int) -> Void) -> Void {
    return { callback in
        dispatch_async(dispatch_get_main_queue()) {
            callback(lhs + rhs)
        }
    }
}

let a = 1
let b = 2

(a <~ b) { result in
    println("OK: \(result)")
}

dispatch_main()