質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

2847閲覧

【Swift】ルーレットを止めた時、止めたタイミングの状態で残したい

RagnAnet1373

総合スコア69

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2017/04/25 02:07

編集2017/04/25 02:12

###前提・実現したいこと
前回の質問で解決した所の
回転を止める所で現在の状態ですと
止めた時に一番最初の状態に戻るので、それを直したいです

###該当のソースコード

swift

1 //CABasicAnimationのtransform.zを使用する 2 let rotationAnimation = CABasicAnimation(keyPath:"transform.rotation.z") 3 4 5 func spinAnim(_ sender: UIView) 6 { 7 rotationAnimation.toValue = CGFloat(Double.pi / 180) * 360//回転角度 8 rotationAnimation.duration = 0.8//アニメーションにかかる時間 9 rotationAnimation.repeatCount = .infinity//何回繰り返すか(MAXFLOATを修正) 10 11 //アニメーションさせたいものにaddする 12 sender.layer.add(rotationAnimation, forKey: "rotationAnimation") 13 } 14 15 func spinStop(_ sender: UIView) 16 { 17 sender.layer.removeAnimation(forKey:"rotationAnimation") 18 }

状態を保存する際にtoValueを入れると保存可能と調べたら出ましたので、
このfunc spinStopを

swift

1 func spinStop(_ sender: UIView) 2 { 3 if let anim = sender.layer.animation(forKey:"transform.rotation.z"){ 4 let base = anim as! CABasicAnimation 5 sender.layer.transform = base.toValue as! CATransform3D 6 sender.layer.removeAnimation(forKey:"rotationAnimation") 7 } 8 }

こう変更した所エラーが出ました

###発生している問題・エラーメッセージ

問題としましては、エラーメッセージなどはなく動くのですが、 ストップボタンを押した時に回転が止まらないようになってしまっています・・・。

###試したこと
このように記述する前にいろいろ試すとエラーメッセージで値が0、nilと言われ続けたので
現在は質問した通りのようにしてエラーをなくせたのですが、その代わり止まらない状態になってしまいました・・・。

###補足情報(言語/FW/ツール等のバージョンなど)
Xcode8.3,Swift3です。

頑張って調べて行くと言っておいてすぐで、大変申し訳ございません・・・。
どれだけ調べて、Swift3用に直して試してもエラーメッセージばかりで、どうしても力不足を感じてしまいました・・・。

ヒントとなるサイトだけでもご教示、ご教授いただけるとありがたいです・・・。
おそらくこのrotationAnimationを開始しようとした時もこのようなことが起こりえそうです・・・・・・。
宜しくお願い致します・・・・・・。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

とりあえずですが、キーの名前が違います。

swift

1if let anim = sender.layer.animation(forKey:"transform.rotation.z"){

transform.rotation.zではなくrotationAnimationです。

投稿2017/04/25 02:35

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RagnAnet1373

2017/04/25 03:00

回答ありがとうございます。 if文を通ることはできました。 ただ、次はエラーメッセージが出てきまして sender.layer.transform = base.toValue as! CATransform3D というところで EXC_BAD_INSTRUCTION(code=EXC_I386_INVOP,subcode=0x0)とでたのですが これはbase.toValueの値が入っていなかったりするのでしょうか?
fuzzball

2017/04/25 03:47

.toValueって CGFloat(Double.pi / 180) * 360 が入っているのではないのでしょうか?
RagnAnet1373

2017/04/25 04:17

もう一度実行エラー出してエラー出ている付近の値を確認をしますと if文のlet anim = sender.layer.animation(forKey:"transform.rotation.z") でanimとsenderの値を比較すると senderが「0x00007fe9f97119c0」に対し、 animが「0x0000610000039be0」と値が食い違っていました これが原因になるのでしょうか・・・・・・? だとするとなぜ値が変動するのか分からないのです・・・・・・。
fuzzball

2017/04/25 04:30

なぜsenderとanimの話をしているのか分かりませんが、この2つは別物なので違うのは当たり前です。 senderはUIView、animはCAAnimation(CABasicAnimation)です。
RagnAnet1373

2017/04/25 06:03

トンチンカンな答えを出して申し訳ございません・・・。 えっと、同じく始めたての友人などにも相談してみたのですが、 つい先ほど知りました、「po」を使って「po base」と検索すると <CABasicAnimation:0x60000022b8a0; beginTimeMode = absolute; beginTime = 21085.5; repeatCount = inf; duration = 0.5; toValue = 6.283185307179586; keyPath = transform.rotation.z> となっておりました。 ここのtoValueをCATransform3Dにキャストするのがまずい?と見解が私の周りでは出たのですが、どうなのでしょうか・・・・・・?
fuzzball

2017/04/25 06:15 編集

表示に関しては、止まってからであればデバッガでいいですが、あらかじめ print(base) を埋め込んでおけばいいです。 >>toValueをCATransform3Dにキャストするのがまずい まずいですし、何のためにtransformに代入しているのかが分かりません。 6.283185307179586と表示されているように、現在のコードでは toValueは2πで固定です。 「状態を保存する」という目的のようですが、上記のようにtoValueは現在の回転角度などを表していません。
RagnAnet1373

2017/04/25 06:40

少し古めのページなのですが、http://captainshadow.hatenablog.com/entry/20110222/1298352073 こちらのサイトに書かれている if (anim == [imageView.layer animationForKey:@"rotateAnimation"]) { // アニメーション終了時の状態で静止させるためには // アニメーションのtoValueプロパティを使用すればよい。 CABasicAnimation *basicAnim = (CABasicAnimation *)anim; imageView.layer.transform = [basicAnim.toValue CATransform3DValue]; [imageView.layer removeAnimationForKey:@"rotateAnimation"]; } こちらを参考に作ったのですが、swift3では通用しないのでしょうか・・・?
fuzzball

2017/04/25 07:11 編集

まず、リンク先のコードは "transform" のアニメーションなので、toValueにはCATransform3Dの値が入っています。(あなたのコードは "transform.rotation.z" のアニメーションなので、toValueにはFloatが入っています) 次に、停止したときの状態がtoValueに入っているかどうかですが、これは実際に試していないので分かりません。ただ、私はアニメーション開始時に設定した値がそのまま入っているのではないかと思っています。(止めたとき、toValueに2π以外の値が入っていたことがありますか?) ちなみに、Z軸の回転角度からCATransform3Dを作るには CATransform3DMakeRotation(角度, 0, 0, 1) でいいんじゃないかと思います。
RagnAnet1373

2017/04/26 01:03

回答遅れて申し訳ございません・・・。 ご指摘していただいたようにアニメーションの仕方を変えているところなのですが、前回回答したリンク先のコードのこの部分をSwift3で直すとどのように書き直すのでしょうか・・・ = [NSValue valueWithCATransform3D:rotateTransform];
fuzzball

2017/04/26 01:42 編集

ドキュメントを読むクセを付けた方がいいですよ。 https://developer.apple.com/reference/foundation/nsvalue/1436556-init リンク先のコードは、アニメーションを最後まで行うことが前提なので、RagnAnet1373さんがやろうとしている「途中でアニメーションを止めたとき」の場合には参考にならないと思いますよ。
RagnAnet1373

2017/04/26 01:52

わかりました・・・。 ドキュメントをしっかり読み込むように意識して今後調査をしていきたいと思います・・・。 >>>リンク先のコードは・・・ 読んでみると確かに「アニメーション終了時に〜〜〜」と書いてありますので、確かに私が実装したいこととは少し違うコードになってるみたいでした・・・。ご指摘ありがとうございます・・・。 別に参考になるサイトがないかをしっかり読むように意識して探してみます・・・。
fuzzball

2017/04/26 02:17

ドキュメントの前に、Xcodeの補完も活用しましょう。 アニメーションを途中で止める方法ですが、 ・停止&破棄(remove)するのではなくポーズ(一時停止)する方法がないかどうか探す。 ・停止させるのではなく、動かないアニメーション(toとfromを同じにする)に切り替える。 以上2つをアイデアとして書いておきます。
RagnAnet1373

2017/04/26 02:25

はい、ありがとうございます・・・。 >>>Xcodeの補完も・・・ Xcodeの補完につきましては、また詳しくサイトを活用してもっと深く知っていこうと思います。 >>>アニメーションを途中で・・・ なるほど・・・、考え方を変えてみるのですね・・・。 分かりました。ご教示いただいたアイデアを参考にコードの組み替えや調査に活かしていきたいと思います。
RagnAnet1373

2017/04/26 06:21

長々とこの問題に付き合ってくださり、ありがとうございました! おかげでどうにか解決できましたのでベストアンサーに選びました! またここから頑張っていきたいと思います!
fuzzball

2017/04/26 07:11

ベストアンサーはお礼で付けるものではありません。 ご自分の回答をベストアンサーにして下さい。
RagnAnet1373

2017/04/26 07:18

わかりました。そのように致します!
guest

0

自己解決

調査開発した結果次のスクリプトで一時停止、プラスして一時停止状態から開始まで持っていくことができました!

swift

1 //ルーレット回転開始 2 func spinStart(_ sender: UIView) 3 { //CABasicAnimationのtransform.zを使用する 4 let rotationAnimation = CABasicAnimation(keyPath:"transform.rotation.z") 5 6 rotationAnimation.toValue = CGFloat(Double.pi / 180) * 360//回転角度 7 rotationAnimation.duration = 0.1//アニメーションにかかる時間 8 rotationAnimation.repeatCount = .infinity//何回繰り返すか 9 10 //アニメーションさせたいものにaddする 11 sender.layer.add(rotationAnimation, forKey: "rotationAnimation") 12 } 13 14 //一時停止 15 func spinStop(_ sender: UIView) 16 { 17 let roulettelayer = sender.layer 18 let pauseTime = roulettelayer.convertTime(CACurrentMediaTime(),from: nil) 19 roulettelayer.speed = 0.0 20 roulettelayer.timeOffset = pauseTime 21 22 //sender.layer.removeAnimation(forKey:"rotationAnimation") 23 } 24 25 //再開 26 func spinRestart(_ sender: UIView) 27 { 28 let roulettelayer = sender.layer 29 let pauseTime = roulettelayer.timeOffset 30 roulettelayer.speed = 1.0 31 roulettelayer.timeOffset = 0.0 32 roulettelayer.beginTime = 0.0 33 let timeSincePause: CFTimeInterval = roulettelayer.convertTime(CACurrentMediaTime(),from: nil) - pauseTime 34 roulettelayer.beginTime = timeSincePause 35 } 36

fuzzballさん、ありがとうございました!

投稿2017/04/26 06:19

RagnAnet1373

総合スコア69

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問