この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
こんにちは!モバイルアプリサービス部の加藤です。
今回の内容はもしかしたらiOS開発者であれば常識かもしれません。
iOSで繰り返しアニメーションを実装していてアニメーションを行っている画面から他の画面に遷移して 再びアニメーションを行っていた画面に戻るとアニメーションが止まってしまっていることに気づきました。 実験として新規に簡単なアニメーションを行うアプリを作成し、本当に止まるのか試してみました。
開発環境
- Xcode 7.1
- iPhone 6s シミュレータ(iOS 9.1)
画面構成
アプリの画面構成は以下のようにタブで2画面を管理するようにしました。 こちらは1つめの画面で左上に配置しているビューがアニメーション対象のビューです。 STARTボタンをタップするとアニメーションを開始するようにします。
こちらは2つ目の画面です。遷移先として使うだけなので特に処理は行いません。
アニメーションのコーディング
STARTボタンをタップした時のアクションメソッドを実装していきます。
self.subView
が1つ目の画面の左上に配置したビューです。
ボタンをタップするとビューが左右に行ったり来たりします。
オプションでUIViewAnimationOptionRepeat
を指定することでアニメーションを繰り返しています。
- (IBAction)userDidTapStartButton:(id)sender {
CGRect toFrame = CGRectOffset(self.subView.frame, 100.0f, 0.0f);
[UIView animateWithDuration:3
delay:0
options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat
animations:^{
self.subView.frame = toFrame;
}
completion:^(BOOL finished) {
if (finished) {
NSLog(@"animation completion finished.");
} else {
NSLog(@"animation completion NOT finished.");
}
}];
}
アニメーション中に画面遷移
実装したSTARTボタンをタップしてアニメーションを行っている最中に2つ目の画面のタブをタップして遷移するとコンソールに下記ログが出力されました。
animation completion NOT finished.
このログは実装したアニメーションのcompletionブロックが引数finishedがNOの状態で呼ばれたことを意味しています。
引数finishedが何を意味するのかUIViewのクラスリファレンスを見ると、completeionブロックの説明に下記記載がありました。
This block has no return value and takes a single Boolean argument that indicates whether or not the animations actually finished before the completion handler was called.
finishedはcompletionハンドラが呼ばれた時にアニメーションが完了しているかどうかを表しています。 つまりfinishedがNOということはアニメーションが途中でキャンセルされたことを意味します。 実際に再び1つ目の画面に戻ってみるとアニメーションが止まってしまっていました。
ちなみにアニメーション中に [self.subView.layer removeAllAnimations]
を呼んでアニメーションを削除しても同じようにcompletionブロックが引数finishedがNOの状態で呼ばれます。
まとめ
ということで繰り返しアニメーションを実装している場合は画面遷移時のアニメーションキャンセルに注意する必要がありそうです。
特に通信時のローディングアニメーションを自前で実装している場合などが該当するかと思います。
必要に応じてviewDidAppear:
などでアニメーションを再開するなどの対処が必要です。