私はこれをしばらくの間理解しようとしていたが役に立たなかった。基本的に、1行1列でアニメーション化するUIImageViewの配列があります。現在、それらはすべて正しく、しかし同時にアニメートします。さらに、現在は同時に実行されているように見えるので、下部のコードはすべてのアニメーションが完了した後にのみ実行するようにします。私はswiftにかなり慣れていないので、forループがどのように機能するかを完全には理解していないと思いますか?私の考えでは、このコードは配列内のすべての画像ビューをループする必要があり、それが完了した後にのみ、下部のコードを実行する必要があります。ループの各反復でhighlightCardsメソッドを呼び出す必要がありますが、それも発生していないようです。正しい画像が移動されると、アレイが正しく開始されることを知っています。
コードは次のとおりです。
PlayedCardsは、カードインデックスを持つintの配列です。
game.boardは、カードオブジェクトの配列です(UIImageView)
ハイライトカード()は、現在再生可能なカードを強調表示するだけです
完了ブロックのコードはロジスティクス専用であり、正しく機能していることがわかります
「新しいゲームをセットアップする」コメントの下のコードは、すべてのアニメーションが完了した後にのみ実行する必要があるものです
for i in 0..<game.playedCards.count {
// update highlights
self.highlightCards()
// animate cards off screen
let endPoint: CGPoint = CGPoint(x: 1000, y: 250 )
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 3, delay: 2, options: UIView.AnimationOptions.curveEaseInOut, animations: {
() -> Void in
self.game.board[self.game.playedCards[i]].center = endPoint
}, completion: {
(Bool) -> Void in
self.game.board[self.game.playedCards[i]].removed = true
self.game.board[self.game.playedCards[i]].removeFromSuperview()
self.currentCardCount = self.currentCardCount - 1
})
}
// set up next turn
game.blueTurn = !game.blueTurn
self.setBackground()
self.setSuitIndicators()
self.highlightCards()
あなたは正しい方向に進んでいます!ここでの唯一の問題は、アニメーション関数が非同期で実行されることです。つまり、次のループに進む前に、前のものがアニメーション化を終了するまで待機しません。
あなたはすでにcompletion
クロージャーを使用する方法の一部です。ただし、前のアイテムの完了後に次のアイテムをアニメーション化するのを待ちたい場合は、基本的に、完了ブロック内からプロパティアニメーターを再度実行する方法を見つける必要があります。
これを行う最良の方法は、関数へのプロパティアニメーション呼び出しを抽出することです。その後、これが簡単になります!
// This is a function that contains what you've included in your code snippet.
func animateCards() {
// update highlights
highlightCards()
// animate cards off screen
let endPoint: CGPoint = CGPoint(x: 1000, y: 250)
recursivelyAnimateCard(at: game.playedCards.startIndex, to: endPoint) {
//set up next turn
self.game.blueTurn = !self.game.blueTurn
self.setBackground()
self.setSuitIndicators()
self.highlightCards()
}
}
// This function replicates your for-loop that animates everything.
func recursivelyAnimateCard(at index: Int, to endPoint: CGPoint, completion: () -> Void) {
// If this triggers, we've iterated through all of the cards. We can exit early and fire off the completion handler.
guard game.playedCards.indices.contains(index) else {
completion()
return
}
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 3, delay: 2, options: UIView.AnimationOptions.curveEaseInOut,
animations: {
self.game.board[self.game.playedCards[index]].center = endPoint
},
completion: { _ in
self.game.board[self.game.playedCards[index]].removed = true
self.game.board[self.game.playedCards[index]].removeFromSuperview()
self.currentCardCount = self.currentCardCount - 1
// Call this function again on completion, but for the next card.
self.recursivelyAnimateCard(at: index + 1, to: endPoint, completion: completion)
})
}
編集:すべてが完了した後、「次のターン」コードを実行する必要があるとは思いませんでした。上記のコードを更新して、すべてのカードが画面から削除された後に起動する完了ハンドラーを含めました。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加