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

时间:2018-05-25 13:56:16

标签: ios swift completionhandler

刚刚学会了如何创建完成处理程序,我原则上理解它们,但我不知道如何将这些想法付诸实践以实现我的需要。

我有以下通用代码和故事板结构:sessionVC(一个UIViewController)和它的UIView持有一个容器视图,其中包含一个embed到动画VC(也是一个UIViewController)及其SKView。

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

我的问题是,我在代码中用什么来代替我想要的效果?(上面提到的,以及在代码注释中的每个***之后)?

// 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
    }
}

3 个答案:

答案 0 :(得分:1)

它应该类似于:

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

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

答案 1 :(得分:1)

遵循惯例,您可以使用略微不同的措辞来声明函数:

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()
}

如果您更喜欢可选的完成处理程序,我。即那些可以是零的,改变这样的功能:

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

答案 2 :(得分:0)

你想要那样的东西吗?

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