我应该写什么完成处理程序?

What Completion Handlers Should I Write?

刚刚学习了如何创建completion handlers,大体上理解了它们,但我不知道如何将这些想法付诸实践来完成我需要的东西。

我有以下通用代码和故事板结构:sessionVC(一个 UIViewController)及其 UIView 包含一个容器视图,其中嵌入了到 animationVC(也是一个 UIViewController)及其 SKView 的转场。

我想从sessionVC中运行在animationVC的SKView中做一系列的动画。我想尽快准备每个动画(例如,当每个先前的动画仍在 运行ning 时),并且我希望每个动画在开始之前等待最后一个动画完成。请参阅下面的代码。

我的问题是,我应该用什么来代替代码中的 ???s 来实现我想要的效果(如上所述,以及代码注释中的每个 *** 之后)?

// TO DELEGATE ANIMATION TO animationVC
protocol AnimateContentDelegate: AnyObject {

    prepareContent(_ Content, contentWasPrepared: ???)
    animateContent(animationDidComplete: ???)
    playAnimation()
    pauseAnimation()
}

// CONTROL THE OVERALL SESSION
class sessionVC: UIViewController {

    // INITIALIZE contentArray

    weak var delegate: AnimateContentDelegate?

    override func viewDidLoad {
        super.viewDidLoad()

        delegate = self.childViewControllers[0] as? AnimateContentDelegate

        runSession(contentArray)
    }

    func runSession(_ contentArray) {

        for content in contentArray {

            delegate?.prepareContent(content, contentWasPrepared: ???)

            // ***DON’T START THE NEXT ANIMATION UNTIL contentWasPrepared
            //    DO CONTINUE THE CURRENT ANIMATION, AND ALLOW INTERACTIONS

            delegate?.animateContent(animationDidComplete: ???)

            // ***DON’T START THE NEXT ANIMATION UNTIL animationDidComplete
            //    DO CONTINUE THE CURRENT ANIMATION, AND ALLOW INTERACTIONS
       }
    }

    @IBAction func playOrPause(_ sender: UILongPressGestureRecognizer) {

         if sender == .possible || sender.state == .ended {

            delegate?.playAnimation()

        } else if sender.state == .began {

            delegate?.pauseAnimation()
        }
    }
}

// PREPARE AND ANIMATE CURRENT CONTENT
class animationVC: UIViewController, AnimateContentDelegate {

    // SET UP SKVIEW

    func prepareContent(_ content: Content, prepCompleteHandler: ???) {
       // PREPARE THE CONTENT
       // ***REPORT WHEN IT IS FINISHED
    }

    func animateContent(animationCompleteHandler: ???) {
        // ANIMATE THE CONTENT
        // ***REPORT IF IT RAN TO COMPLETION
   }

    func playAnimation() {
        skView?.scene?.isPaused = false
    }

    func pauseAnimation() {
        skView?.scene?.isPaused = true
    }
}

它应该看起来像:

func prepareContent(_ content: Content, completionHandler: @escaping (Bool, Any?) -> Void) -> Void {

   var finished : Bool = false
   var output : Any? = nil

   // prepare the content
   // possibly update the output

   //when ready : 
   finished = true
   completionHandler(finished, output)

}

然后你使用它:

prepareContent(content: content, completionHandler: { (f, o) in 
   if f {
      if o != nil {
          //do something
      }
      //else handle error
   }
   //else handle error
})

您可以根据需要调整它,根据需要添加或多或少的输出、错误日志等。

你想要这样的东西吗?

protocol AnimateContentDelegate: AnyObject {
    func prepareContent(content : Content, contentWasPrepared: ((Bool) -> Void)?)
    func animateContent(animationDidComplete: ((Bool) -> Void)?)
    func playAnimation()
    func pauseAnimation()
}

class YourObject : AnimateContentDelegate {

func prepareContent(content: Content, contentWasPrepared: ((Bool) -> Void)?) {
    // prepare content
}

func animateContent(animationDidComplete: ((Bool) -> Void)?) {
    // animate content
}

func playAnimation() {

}

func pauseAnimation() {

}

}

这样使用:

let yourObject = YourObject()
yourObject.animateContent(animationDidComplete: { finished in
    // animation did complete
})

按照通常的约定,您将使用稍微不同的措辞声明函数:

prepareContent(_ Content, completionHandler: { () -> Void })
animateContent(completionHandler: { () -> Void })

然后,在 SET UP SKVIEW 下面,您可以这样调用委托函数:

delegate?.prepareContent(content, completionHandler: {
    self.delegate.animateContent(completionHandler: {
        // do whatever needs to be done upon completion
    })
})

(您也可以使用尾随闭包语法。) 通过像这样嵌套委托调用,您可以确保仅在准备完成后才执行动画。

函数体看起来像这样:

func prepareContent(_ content: Content, completionHandler: (() -> Void)) {
    // ...
    completionHandler()
}

func animateContent(completionHandler: (() -> Void)) {
    // ...
    completionHandler()
}

如果您更喜欢可选的完成处理程序,我。 e.可以为nil的,把函数改成这样:

func prepareContent(_ content: Content, completionHandler: (() -> Void)?) {
    // ...
    completionHandler?()
}