刚刚学会了如何创建完成处理程序,我原则上理解它们,但我不知道如何将这些想法付诸实践以实现我的需要。
我有以下通用代码和故事板结构: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
}
}
答案 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
})