CATransitionとタイマー
タイマーで0.01秒ごとに数字を1増やし、その数字をキーとして辞書から取り出した値をUILabelに表示するというアプリを作りました。が、ラベルにアニメーションをつけたところ、それも0.01秒ごとに実行されてしまい、ラベルが点滅したりしてしまいます。
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(labelUpdate), userInfo: nil, repeats: true)
}
func labelUpdate() {
testInt += 1
if let label = testDict[testInt] {
let anime = CATransition()
anime.type = kCATransitionMoveIn
anime.subtype = kCATransitionFromBottom
anime.duration = 0.2
testLabel.layer.add(anime, forKey: nil)
testLabel.text = label
}
}
辞書のキーは毎回異なるのでこのように、キーがnilでないときにラベルを更新という処理にしたのですが、nilのときにもanimeが実行されているようです・・・
変更するときのみ、アニメーションしてくれればそれでいいのですが・・・
追記
辞書は例えばvar testDict = [1: "りんご", 200:"バナナ", 470:"卵"]
のようなものです。
testIntは任意のタイミングでUIButtonでリセットします。
理想は上記の例で言えば"りんご"から"バナナ"に変更されるときに1度だけアニメーションするというものです。
今のままで実行すると、"りんご"や"バナナ"と表示されたUILabelが点滅したあとに突然指定したアニメーションをしたり、"りんご"という文字が点滅した文字の下にもう一つ現れてそこに点滅している文字に重なったりと、正しい動きではないと思われる動きになってしまいます。
さらに追記
再度、確認させてもらったところ、
点滅したり文字が重なったりということは起こらず、ただアニメーションに関するコードが全くないかのように普通に文字が入れ替わるという動作になってしまいました。
コード追加
var testDict = ["00:01": "りんご", "00:05":"バナナ", "00:07":"卵"]
func labelUpdate() {
let min = Int(player.currentPlaybackTime) / 60
let sec = Int(player.currentPlaybackTime.truncatingRemainder(dividingBy: 60))
timeKey = String(format: "%02d:%02d", min, sec)
//この部分が問題でした。大変申し訳ございません
if let label = testDict[timeKey] {
let anime = CATransition()
anime.type = kCATransitionMoveIn
anime.subtype = kCATransitionFromBottom
anime.duration = 0.2
testLabel.layer.add(anime, forKey: nil)
testLabel.text = label
}
}
timerを0.01秒ごとにしたのはmm:ssが実際の再生中の曲の再生時間と同期するためです。
currentPlaybackTimeが1秒増えるタイミングとtimerで更新しているmm:ssの値がずれてしまうとコンマ数秒単位でずれてしまうので・・・
しかしこのせいで、testDict[timeKey]がnilでないときの処理が0.01x100回実行されてしまうようです。
点滅するのは100回MoveInが実行されるため。
重なって表示されるのは次の秒数になった瞬間、testLabel.text = labelが保持されたまま0.2秒かけてアニメーションも実行されたためでした。
本当に申し訳ない話ですが、ここまで気がつきませんでした。
見た目では問題なかった(気がつかなかった)のですが、こうなるとtestLabel.text = labelも100回繰り返されていることになっていますよね・・・。
その場合、どうしたらいいのでしょうか。
今は辞書キーがnilじゃなかったら更新を1秒に100回繰り返していますが、
1度変わってしまえば残り99回は必要ありませんし、そうすればアニメーションも正常に機能すると思うのです・・・。
つまり、辞書キーがnilじゃないとき、1度のみUILabelの表示を更新してそのときアニメーションを実行、また別のキーと値が取り出せたらそれも一回のみUILabelの表示の更新とアニメーションという処理をしたいということでした。