【问题标题】:Using custom operators with completion block使用带有完成块的自定义运算符
【发布时间】:2015-09-01 20:50:36
【问题描述】:

简而言之,假设我定义了一个运算符:

infix operator <~ {
    associativity left
    precedence 160
}

假设我使用这个操作符做两个对象之间的一些工作,所以我定义了这样的函数:

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

现在我们不能返回任何东西,因为操作符函数正在做异步工作,我们也不能为闭包使用更多的参数。因为异步函数可能会运行几秒钟,所以我需要一个在异步任务完成时运行的回调。问题是您是否可以将运算符与异步函数一起使用?我尝试了各种解决方案,但似乎都不起作用。

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

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

【问题讨论】:

    标签: ios swift asynchronous swift2


    【解决方案1】:

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

    至少,你必须(something &lt;~ 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()
    

    【讨论】:

      【解决方案2】:

      只要你愿意搭建一些脚手架,你就可以做到这一点。这不可能开箱即用。

      让我们想想我们如何在没有运算符的情况下进行此操作。我们将有一个操作队列,当每个操作完成后,我们将添加下一个操作。并且每个操作都应该在完成后通知队列。

      因此操作员只负责将操作添加到队列中。如果您想要更复杂的实现,请查看任何适用于 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

      操作1

      调用第一个实现,它将 Operation1 和 Operation2 都放入队列,并将 Operation1 添加为 Operation2 的依赖项。我们从这里返回一个包装 Operation2 的 QueuedOperation,因为当我们向前链接时,下一个对 Operation2 有依赖关系,但 Operation2 不能再次排队。

      返回不同的类型并分派给具有不同类型签名的函数允许我们这样做。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-24
        • 1970-01-01
        • 1970-01-01
        • 2012-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多