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

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

ただいまの
回答率

90.37%

  • Swift

    9165questions

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

  • iOS

    4873questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

  • Swift 2

    1341questions

    Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

UIView.animateWithDurationの使い方について

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,352

lyzmfeqpxs54

score 165

現在swiftでクイズの作成を行っています。問題文の表示のところで行き詰まっております。下記のようにして問題文の表示を1行目から順に表示させています。次の問題に進む際には下記の問題削除メソッドでラベルを削除し、また1行目からラベルの表示を行っています。次の問題メソッドは回答してから1秒後に呼ばれます。

現状では表示自体は正しく動いてはいるのですが、問題文の表示中に回答を行い次の問題文の表示に移行した場合に前回のラベルが表示されてしまいます。

具体例としまして今の問題文が4行、次の問題が2行とします。
今の問題文が仮に2行目を表示している時に問題の回答を行なったとします。
次の問題メソッドがよばれラベルの削除を行ない、次の問題が表示されるのですが前回の3行目と4行目も続けて表示さてしまいます。

問題文の表示をUIView.animateWithDurationの終了の度に次の行の文を表示するというこの方法はあまりよくないのでしょうか(他に思いつかなかったのですが・・・)。
この方法の場合次の問題がよばれたらUIView.animateWithDurationを停止するようにしたほうがよいのでしょうか。また、停止はどのようにおこなえばよいのでしょうか。UIView.animateWithDurationの停止は調べてみたのですがなかなか出てきませんでした・・・。

長文かつ分かりにくい文章で申し訳ありません。
ご助言をいただければ幸いです。

//問題文を表示するメソッド
    func questionDisplay(){

        var str = mondaiArray[3].componentsSeparatedByString("/") // mondaiArray[3]には問題文が入っています
        str += ["","",""]                //問題文が1行の場合に空白を作らないように(この方法もよくないと思ってはいるのですが・・・)

        // 問題文各行の文字数を数える
        let line1 = str[0].characters.count
        let line2 = str[1].characters.count
        let line3 = str[2].characters.count
        let line4 = str[3].characters.count
        // Duuble型にキャスト(animateWithDurationに代入するため)
        let line1CG:Double = Double(line1)
        let line2CG:Double = Double(line2)
        let line3CG:Double = Double(line3)
        let line4CG:Double = Double(line4)
        // ラベルの作成 幅0のラベル。後で問題文の文字列に対してぴったりの幅のラベルをアニメーション終了とすることで、問題文が1文字目から順に表示されるようにしている。 scWidとscHeiはそれぞれ画面の幅と高さ(screenwidth)
        let myLabel1: UILabel = UILabel(frame: CGRectMake(scWid*0.18 ,scHei*0.15 ,0 ,scHei*0.08))
        let myLabel2: UILabel = UILabel(frame: CGRectMake(scWid*0.18 ,scHei*0.20 ,0 ,scHei*0.08))
        let myLabel3: UILabel = UILabel(frame: CGRectMake(scWid*0.18 ,scHei*0.25 ,0 ,scHei*0.08))
        let myLabel4: UILabel = UILabel(frame: CGRectMake(scWid*0.18 ,scHei*0.30 ,0 ,scHei*0.08))
        // タグ番号の追加
        myLabel1.tag = 7
        myLabel2.tag = 8
        myLabel3.tag = 9
        myLabel4.tag = 10
        // フォントサイズの指定
        myLabel1.font = UIFont.systemFontOfSize(14)
        myLabel2.font = UIFont.systemFontOfSize(14)
        myLabel3.font = UIFont.systemFontOfSize(14)
        myLabel4.font = UIFont.systemFontOfSize(14)
        // 文字の色を白にする.
        myLabel1.textColor = UIColor.whiteColor()
        myLabel2.textColor = UIColor.whiteColor()
        myLabel3.textColor = UIColor.whiteColor()
        myLabel4.textColor = UIColor.whiteColor()
        //テキストの表示
        myLabel1.text = str[0]
        myLabel2.text = str[1]
        myLabel3.text = str[2]
        myLabel4.text = str[3]
        // ViewにLabelを追加.
        self.view.addSubview(myLabel1)

        UIView.animateWithDuration(line1CG/15, delay: 0.0, options : UIViewAnimationOptions.CurveLinear, animations: {() -> Void  in    //ここでは文字数に応じて幅がぴったりラベルを表示しています
            let myaLabel1_frame: CGSize = CGSizeMake(240, 50) //一旦大まかなサイズを指定
            let myaLabel1_text_frame: CGSize = myLabel1.sizeThatFits(myaLabel1_frame)
            let myaLabel1_text_width: CGFloat = myaLabel1_text_frame.width
            myLabel1.frame = CGRectMake(self.scWid*0.18 ,self.scHei*0.15 ,myaLabel1_text_width ,self.scHei*0.08)
            //return
            },
            completion: {(finished: Bool) -> Void in
                // アニメーション終了後の処理 1行目の表示が終わったら2行目の表示
                self.view.addSubview(myLabel2)
                UIView.animateWithDuration(line2CG/15, delay: 0.0, options : UIViewAnimationOptions.CurveLinear, animations: {() -> Void  in
                    let myaLabel2_frame: CGSize = CGSizeMake(240, 50)
                    let myaLabel2_text_frame: CGSize = myLabel2.sizeThatFits(myaLabel2_frame)
                    let myaLabel2_text_width: CGFloat = myaLabel2_text_frame.width
                    myLabel2.frame = CGRectMake(self.scWid*0.18 ,self.scHei*0.20 ,myaLabel2_text_width ,self.scHei*0.08)
                    //return
                    },
                    completion: {(finished: Bool) -> Void in
                        // アニメーション終了後の処理 同じく3行目
                        self.view.addSubview(myLabel3)
                        UIView.animateWithDuration(line3CG/15, delay: 0.0, options : UIViewAnimationOptions.CurveLinear, animations: {() -> Void  in
                            let myaLabel3_frame: CGSize = CGSizeMake(240, 50)
                            let myaLabel3_text_frame: CGSize = myLabel3.sizeThatFits(myaLabel3_frame)
                            let myaLabel3_text_width: CGFloat = myaLabel3_text_frame.width
                            myLabel3.frame = CGRectMake(self.scWid*0.18 ,self.scHei*0.25 ,myaLabel3_text_width ,self.scHei*0.08)
                            //return
                            },
                            completion: {(finished: Bool) -> Void in
                                // アニメーション終了後の処理 同じく4行目
                                self.view.addSubview(myLabel4)
                                UIView.animateWithDuration(line4CG/15, delay: 0.0, options : UIViewAnimationOptions.CurveLinear, animations: {() -> Void  in
                                    let myaLabel4_frame: CGSize = CGSizeMake(240, 50)
                                    let myaLabel4_text_frame: CGSize = myLabel4.sizeThatFits(myaLabel4_frame)
                                    let myaLabel4_text_width: CGFloat = myaLabel4_text_frame.width
                                    myLabel4.frame = CGRectMake(self.scWid*0.18 ,self.scHei*0.30 ,myaLabel4_text_width ,self.scHei*0.08)
                                    //return
                                    },
                                    completion: {(finished: Bool) -> Void in
                                        // アニメーション終了後の処理

                                })

                        })

                })

        })

    }

    //次の問題を表示するメソッド
    func nextProblem(){
        labelRemove()   // UILabel削除

                   (以下略)

}
//各種ラベルを削除するメソッド
func labelRemove(){
        // self.viewの上に乗っているオブジェクトを順番に取得
        for v in self.view.subviews {
            // オブジェクトの型がUILabel型で、タグが10番以下のオブジェクトを取得 7〜10:問題表示ラベル
            if let v = v as? UILabel where v.tag <= 10  {
                // そのオブジェクトを親のviewから取り除く
                v.removeFromSuperview()
            }
        }
    }

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

アニメーションの停止は、アニメーションしているビューのレイヤーに対してremoveAllAnimations()を呼び出すことでできます。
(参考)
https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CALayer_class/#//apple_ref/occ/instm/CALayer/removeAllAnimations

なお、アニメーション処理が途中でキャンセルされるとアニメーション完了時(completionハンドラ)のfinishedパラメータがfalseで呼び出されます。

提示されたソースコードの修正ポイントを具体的に言うと、

  1. labelRemove()関数で v.removeFromSuperView()する直前にv.layer.removeAllAnimations()を入れてアニメーションを削除する。
  2. アニメーション処理の各completionハンドラの処理でfinishedパラメータを参照し、finishedがfalseであれば続きのアニメーションを開始しないようにする。

これでうまくいくと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/04 13:32

    ご教示いただいた内容で無事解決いたしました!本当にありがとうございます!

    v.layer.removeAllAnimations()の追加および
    // アニメーション終了後の処理
    if finished == false {
    return
    }
    の追加で解決できました。

    キャンセル

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

  • ただいまの回答率 90.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Swift

    9165questions

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

  • iOS

    4873questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

  • Swift 2

    1341questions

    Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。