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

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

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

Xcode 7は、ソフトウェア開発のためのアップルの統合開発環境であるXcodeのバージョン。UIを作成するために用いるグラフィカルツールです。iOS9/OS X El Capitan/watchOS2に対応。Swift 2コンパイラーが搭載されています。

Xcode

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

Swift

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

Swift 2

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

Q&A

解決済

2回答

1690閲覧

selectorを使ってviewDidAppear内のメソッドを呼び出すには

burdock

総合スコア12

Xcode 7

Xcode 7は、ソフトウェア開発のためのアップルの統合開発環境であるXcodeのバージョン。UIを作成するために用いるグラフィカルツールです。iOS9/OS X El Capitan/watchOS2に対応。Swift 2コンパイラーが搭載されています。

Xcode

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

Swift

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

Swift 2

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

0グッド

0クリップ

投稿2017/05/18 14:39

編集2017/05/18 14:46

現在、アプリの起動直後にボタンが回転するというアニメーションを
考えています。
少々説明が難しいのですが、質問させていただきます。
質問内容は下記の通りです。
■質問内容
selectorを使ってviewDidAppear内のメソッドを呼び出すには
どのようなコーディングをすべきでしょうか。

はじめは、下記の様なコーディングをしました。

class LoginViewController: UIViewController { @IBOutlet weak var buttonTest: UIButton! override func viewDidLoad() { super.viewDidLoad() Timer.scheduledTimer(timeInterval: 8.0, target: self, selector: #selector(self.rotate), userInfo: nil, repeats: true) } func rotate() { UIView.animate(withDuration: 6.0, delay: 0.0, options: [.curveEaseInOut], animations: { 回転の処理 } } }

ボタンは回転するのですが、
アプリが起動して数秒たってから回転のアニメーションが始まってしまいます。
アプリが起動してアニメーションが始まるまでの時間を短くさせたくて
下記の様なコーディングをしました。

class LoginViewController: UIViewController { @IBOutlet weak var buttonTest: UIButton! override func viewDidLoad() { super.viewDidLoad() Timer.scheduledTimer(timeInterval: 8.0, target: self, selector: #selector(self.rotate), userInfo: nil, repeats: true) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated: Bool) func rotate() { UIView.animate(withDuration: 6.0, delay: 0.0, options: [.curveEaseInOut], animations: { 回転の処理 } } }

上記のようなコーディングをすると、#selectorのところで以下の様なエラーに
なりました。

イメージ説明

そのため、#selectorのところを下記の様にコーディングをしてみました。

Timer.scheduledTimer(timeInterval: 8.0, target: self, selector: #selector(LoginViewController.viewAppear(_:)), userInfo: nil, repeats: true)

コーディングエラーはでないものの
実機テストを行うとアニメーションが始まらなくなりました。
selectorを使ってviewDidAppear内のrotate()を呼び出すには
どのようなコーディングをすべきでしょうか。
お手数をおかけいたしますが、ご教示いただけますでしょうか。
よろしくお願い致します。

■補足
swift:3
xcode:8.2.1

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

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

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

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

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

guest

回答2

0

ベストアンサー

質問のエラーが出ている原因は、必要な処理をselectorでうまく指定できないためであり、
その問題の根本はメソッド(viewDidAppear)内でメソッド(rotate)を定義しているためですが、
そのエラーを直しても「アプリが起動してアニメーションが始まるまでの時間を短くさせたくて」
というのは実現できません。

Timer.scheduledTimer(timeInterval: 8.0, 〜の意味はわかっているでしょうか?
これは、タイマーをかけて8秒後にselectorで指定したメソッドを呼び出すということですから、
これを使ってアニメーション開始することを修正しない限り、
どうやってもアニメーション開始までに8秒かかります。

画面を表示してすぐにアニメーションしたいのであれば、
タイマーをかけてselector指定でアニメーションを開始するのではなく、
viewDidAppearから直接rotateメソッドを呼び出せばいいです。

(修正例)

swift

1 class LoginViewController: UIViewController { 2 @IBOutlet weak var buttonTest: UIButton! 3 override func viewDidLoad() { 4 super.viewDidLoad() 5 // Timer.scheduledTimerは使用しない 6 } 7 override func viewDidAppear(_ animated: Bool) { 8 super.viewDidAppear(animated: Bool) 9 // rotateメソッド定義 10 func rotate() { 11 // アニメーション開始 12 UIView.animate(withDuration: 6.0, delay: 0.0, options: [.curveEaseInOut], animations: { 13 // 回転の処理 14 } 15 } 16 // rotateメソッド呼び出し 17 rotete() 18 }

ただ、rotateメソッドをviewDidAppearの中からしか使わないのであれば、
そもそもメソッド内にメソッドなど定義せずに直接アニメーション処理した方がスッキリします。

swift

1 override func viewDidAppear(_ animated: Bool) { 2 super.viewDidAppear(animated: Bool) 3 // アニメーション開始 4 UIView.animate(withDuration: 6.0, delay: 0.0, options: [.curveEaseInOut], animations: { 5 // 回転の処理 6 } 7 }

これで十分だと思います。


(5/19 11:15追記)

リピートタイマーを使ってアニメーションを繰り返すのであれば、
以下のようにすればいいです。

(例)

swift

1class ViewController: UIViewController { 2 3 @IBOutlet weak var button: UIButton! 4 5 // タイマー 6 var timer = Timer() 7 8 override func viewDidAppear(_ animated: Bool) { 9 super.viewDidAppear(animated) 10 // リピートタイマー開始 11 timer = Timer.scheduledTimer(timeInterval: 8.0, target: self, selector: #selector(self.rotate), userInfo: nil, repeats: true) 12 // 初回だけすぐにタイムアウトさせる 13 timer.fire() 14 } 15 16 override func viewWillDisappear(_ animated: Bool) { 17 super.viewWillDisappear(animated) 18 timer.invalidate() 19 } 20 21 func rotate() { 22 self.button.transform = CGAffineTransform(rotationAngle: 0) 23 // アニメーション開始 24 UIView.animate(withDuration: 6.0, delay: 0.0, options: [.curveEaseInOut], animations: { 25 // 回転の処理 26 self.button.transform = CGAffineTransform(rotationAngle: CGFloat.pi / 2) 27 }) 28 } 29}

ポイントは、タイマーはviewDidLoadではなくviewDidAppearのタイミングで開始することと、rotateメソッドはviewDidAppearの外で定義することです(でないとタイマーから呼び出せません)。

そうした上で、タイマー開始直後にtimer.fire()を使えば、初回だけすぐにタイムアウトさせて、すぐにアニメーションを開始することができます。

それと、ここから別の画面に遷移するなら、その時にタイマーを止める必要がありますので、念のためにviewWillDisappearでタイマーを止める処理も入れておきました。

投稿2017/05/18 19:18

編集2017/05/19 02:23
TakeOne

総合スコア6299

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

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

burdock

2017/05/19 00:22 編集

回答頂いたとおりviewDidLoad内でTimer.scheduledTimerは記述せずに、viewDidAppear内でUIView.animateを記述すると起動してすぐにアニメーションが開始することができました。ありがとうございます。また、質問を重ねる形になり申し訳ないのですが。回転のアニメーション自体は約3秒ほどで終了するものです。アプリが起動して(約3秒間の)回転のアニメーションを8秒ごとに実施したいと思い、viewDidLoad内でTimer.scheduledTimerを使用していました。プログラミングを独学でやっていてつまづくことが多く悩んでしまうのですが、回転のアニメーションを8秒ごとに実施したい場合、Timer.scheduledTimerを使用してコーディングをすべきでしょうか。また、Timer.scheduledTimerを使わない方法などございましたら、ご教示いただけますでしょうか。
fuzzball

2017/05/19 01:02 編集

回答するのもあれなのでここに書きます。ちょっと見づらいですけど。 時間の指定は、全体で8.0sec、回転処理は3.0sec(8.0*0.375)となっています。 UIView.animateKeyframes(withDuration: 8.0, delay: 0.0, options: [.repeat], animations: { UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 0.375, animations: { //回転処理 }) }, completion: nil)
TakeOne

2017/05/19 02:16

なるほど、アニメーションを8秒ごとに繰り返す目的があって「repeats:true」のリピートタイマーを起動していたのですね。 見落としていました。 fuzzballさんのやり方でもできると思いますが、burdockさんのやり方を尊重して、リピートタイマーを使ってアニメーションを繰り返すならこうするという例を回答に追記しておきます。
burdock

2017/05/19 09:34 編集

回答コードを元に再度コーディングさせていただいたところ、自分の思い描いたアニメーションに非常に近くなりました。viewWillDiappearも使用するなどライフサイクルの勉強になりました。ありがとうございます。
guest

0

反復してアニメーションさせるためにTimerを試されたのでしょうか?
UIViewAnimationOptionsには反復に関する設定があるようですので、こちらを利用するという手が使えるかもしれません。
なお、オートレイアウト機能などとの干渉により、viewDidLoadの時点でアニメーションさせようとすると意図通りにならない可能性がありますので、TakeOneさんのようにviewDidAppearまで待った方がよさそうです。

投稿2017/05/18 22:08

Bongo

総合スコア10807

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

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

burdock

2017/05/19 00:42

質問の説明不足で申し訳ありません。以前UIViewAnimationOptionsのrepeatCount = MAXFLOATなど試しましたが、絶え間なく回転し続けてしまい、なんだか忙しいアニメーションだったので、約3秒間の回転アニメーションをアプリが起動して8秒間隔で実施したいと思い、質問内容のようにTimerを使いました。回答いただきありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問