【Swift】UIViewControllerの再読み込み・リロード(reload)。ViewDidLoadに戻りたい時。
こんにちは、iPhoneアプリ開発者の中川です。
UITableViewのようにUIViewControllerをリロードしたいなぁと思う場面が出てきました。UITableViewの場合は、tableView.reloadDataとしてやればいいのですが、UIViewControllerの場合はそんな便利なメソッドはないですよね。というわけで、UIViewControllerのリロードをする方法を考えました。
まず理解すべきは「UIViewController の viewライフサイクル」というものなのですが、そんなまどろっこしいことは別に知らなくてもいいよ!って方もいると思うので結果から書きます。
1 2 |
loadView() viewDidLoad() |
このふたつのメソッドを実行することでUIViewControllerをUITableViewのようにreloadすることができます。
さてさて、このメソッドを実行するにあたって理解すべきライフサイクルですが、ライフサイクルというのはUIViewControllerの画面読み込み時のdelegateの実行順序です。その実行順序が以下。
ここで特にどれがどれだかわからなくなるのは以下の4つのメソッドだと思います。
loadView:
controllerが制御するviewを作成する。
viewDidLoad:
UIViewControllerのviewがメモリに読み込まれた後に呼ばれる。
viewWillAppear:
UIViewControllerのviewが表示される時にview controllerに通知される。
viewDidAppear:
view controllerのviewがwindowに追加されたらview controllerに通知される。
注目すべきは、赤文字の部分です。ViewDidLoadに戻りたいので、loadViewを呼んでViewを作成したのちに、ViewDidLoadが呼ばれなければなりません。そして、通知されるメソッドは呼ばせる必要はありません。
どうでしょう。ちょっとややこしい話でしたが、このライフサイクルを理解していれば、UIViewControllerも再読み込みすることができます。必要な場面に遭遇したら試してみてください。
ディスカッション
コメント一覧
こんにちは。初めまして。
私、iPhoneアプリ開発をしており、中川様のページを参考にさせていただきました。
誠にありがとうございます。
一点ご質問があり、お手数をおかけいたしますが、ご確認いただけましたら幸いでございます。
(ハマってしまい2日なにもできておらず、、、ご迷惑をおかけいたします。)
▼
・loadView()/ViewDidLoad() の2つでViewの更新を行っておりますが、iOS9以上では正常に動作致しますが、iOS8では画面が表示されない状況です。
なにか、原因となることがお分かりでしたら教えていただきたく思います。StoryboardにてUI部品を配置しているため、症状が発生してしまうのでしょうか。
お忙しい中と思いますが、ご返事いただけましたら幸甚に存じます。
mos様。コメントありがとうございます。
viewの再読み込み(リロード)に関して、私も度々悩まされます。
2日ハマっているとのことで、心中お察しいたします。辛いですよね。。
私の方で新規プロジェクトを作成し、StoryboardにてUI部品を貼り付けてテストを行ってみました。
結果から言うと、iOS8.1シミュレータでloadView()/ViewDidLoad()で正常にリロードすることができました。(最後にサンプルコードを載せておきます。)
さて、なぜloadView()/ViewDidLoad()で画面が表示されないのかですが。。
考えられる可能性としては、viewWillAppear(animated: Bool)の部分で何かしら画面初期化の処理をしていないか。ということです。
しかし、iOS9では正常に動作しているとのことなので書いてなさそうですよね。
あとは、UIViewControllerのライフサイクルでライフサイクルの解説が掲載されているのですが、”Storyboardやxibなど、InterfaceBuilderを利用している場合はloadViewを呼び出してはならない。”と書いてあります。もしかしたら、loadviewが何かしら動作しているのかもしれません。
しかし、基本的にはloadviewを呼び出さないとリロードをかけることはできないはずです。下のサンプルコードでもloadview()をコメントアウトした場合、リロードがかかりませんでした。
お手数ですが、以上のことをご確認いただき、再度コメントをいただけると幸いです。
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var myLabel: UILabel!
@IBOutlet weak var myButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
}
@IBAction func onclickMyButton(sender: AnyObject) {
myLabel.alpha = 0
myButton.alpha = 0
}
@IBAction func reload(sender: AnyObject) {
self.loadView()
self.viewDidLoad()
}
}
ご丁寧な返信、ありがとうございます。
早速、色々な方法で試してみました。結論から申しますと、タイマーを用いてUI部品等の表示の更新を行うような、別の方法に切り替えました。loadViewの動作を呼び出して、追加し試してみましたが、どうもうまく動作してくれませんでした。
中川様同様に、loadViewをコメントアウトした場合、症状が再現されず、リロードできていない状況です。loadViewの動作が起因しているかと思っております。しかし、ソースコードの量も多くなっているため、もしかしたら他の部分で起因しているかもしれません。
結局、原因がわからずじまいで終わってしまいました。わかれば、便利に使えていたのに。。。
ご協力いただきまして、ありがとうございました。