## はじめに
人それぞれわかりやすいコードの書き方があるとは思うが
毎回違う書き方をしていてはメンテ性も悪いので、ViewControllerのコードを自分なりに標準化したいと思いメモ。
import UIKit
class ViewController: UIViewController {
//こ こ で U I の イ ン ス タ ン ス 化
override func viewDidLoad() {
super.viewDidLoad()
//viewがメモリに読み込まれた後に一度だけ呼ばれる
//表示サイクルで1度だけ呼ばれる為クラス内で利用するオブジェクトの初期化などに適する
//viewに対する追加の初期化処理
//ネットワーク通信
//一度だけ行う処理
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//viewが表示される直前に呼ばれる(初回表示以外にもバックグラウンド復帰、タブ切り替えなど)
//UIを非表示や非活性にする処理
//アプリの状態に応じたviewの更新
//まだviewが確定されていない為、計算コストの高い処理は避ける
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
//superViewのboundsが変更される直前に呼ばれる(デバイスの向きが変わるなど)
//safeAreaはviewWillLayoutSubviewsが一番早く取れるタイミング
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
//subViewのレイアウトが完了した際に呼ばれる(viewのboundsが確定される)
//viewのサイズを用いた処理
//viewの配置メソッドの実行
setupViews()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
//viewが画面に表示された直後に呼ばれる(バックグラウンド復帰時やタブ切り替え時など複数回呼ばれる)
//UI表示が完了しているので、UI表示に関係のない処理を実行するのに適する(ログ送信など)
//CoreDataへのデータの書き込み
//アニメーションや動画の再生
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
//viewが取り除かれる直前に呼ばれる(Modal,Push遷移)
//ViewControllerでの変更の保存など
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
//viewが取り除かれた直後に呼ばれる(Modal,Push遷移)
//通知の解除など(iOS9以降は自動解除)
}
func setupViews(){
//viewの配置メソッド(viewDidLayoutSubviewsで実行)
//safeAreaの取得
let safeArea = view.safeAreaInsets
//こ こ で U I の サ イ ズ 、 位 置 の 設 定
}
}
// MARK: - delegateメソッド
extension ViewController : UITextFieldDelegate{
//delegate毎にextensionで区切って設定
}
## 参考にさせていただきました
UIKitのView表示ライフサイクルを理解する
https://qiita.com/shtnkgm/items/f133f73baaa71172efb2
ViewControllerのライフサイクル
https://medium.com/@shiba1014/viewcontrollerのライフサイクル-37151427bda5
【swift】viewDidLayoutSubviews、layoutSubviews
https://scleapt.com/swift_viewdidlayoutsubviews/
本記事の内容に差し支える点がある場合はご連絡ください。
## 最後に(戯言)
私のような個人開発の素人の場合、書籍やインターネットを参考にしながら何とか動く様にコーディングをするしか無いけど、
やはり、参考にさせて頂く書籍や記事によって同じことを解説していてもコードの考え方が違ったりしていて、混乱をきたしてしまうのがプログラミングの敷居の高い一因なんだろうなと感じる。
その混乱を最小限にするためにも基礎が大事なんだろうなと思った。
アドバイス大歓迎です
## 全コード
import UIKit
class LineViewController: UIViewController {
let lineNoLabel = UILabel()
let lineNoTF = UITextField()
let doneButton = UIButton()
//viewがメモリに読み込まれた後に一度だけ呼ばれる
override func viewDidLoad() {
super.viewDidLoad()
//用途:ViewControllerの表示サイクルで1度だけ呼ばれる為クラス内で利用するオブジェクトの初期化などに適する
//・viewに対する追加の初期化処理
//・ネットワーク通信
//・一度だけ行う処理
//lineNoLabelの設定
lineNoLabel.text = "Line No"
view.addSubview(lineNoLabel)
//lineNoTFの設定
lineNoTF.delegate = self
lineNoTF.borderStyle = .roundedRect
view.addSubview(lineNoTF)
//doneButtonの設定
doneButton.backgroundColor = .magenta
doneButton.setTitle("Done", for: .normal)
doneButton.addTarget(self, action: #selector(doneTaped), for: .touchUpInside)
view.addSubview(doneButton)
}
//viewが表示される直前に呼ばれる(初回表示以外にもバックグラウンド復帰、タブ切り替えなど)
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//UIを非表示や非活性にする処理
//アプリの状態に応じたviewの更新
//まだviewが確定されていない為、計算コストの高い処理は避ける
}
//superViewのboundsが変更される直前に呼ばれる(デバイスの向きが変わるなど)
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
//safeAreaはviewWillLayoutSubviewsが一番早く取れるタイミング
print("SafeArea=",view.safeAreaInsets)
}
//subViewのレイアウトが完了した際に呼ばれる(viewのboundsが確定される)
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
//viewのサイズを用いた処理
//viewの配置メソッドの実行
setupViews()
}
//viewが画面に表示された直後に呼ばれる(バックグラウンド復帰時やタブ切り替え時など複数回呼ばれる)
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("viewDidAppear")
//UI表示が完了しているので、UI表示に関係のない処理を実行するのに適する(ログ送信など)
//CoreDataへのデータの書き込み
//アニメーションや動画の再生
}
//viewが取り除かれる直前に呼ばれる(Modal,Push遷移)
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
//ViewControllerでの変更の保存など
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
//通知の解除など(iOS9以降は自動解除)
}
func setupViews(){
//safeAreaの取得
let safeArea = view.safeAreaInsets
//UIパーツの配置エリアの大きさ
let partsArea_W = view.frame.width - safeArea.left - safeArea.right
let partsArea_H = view.frame.height - safeArea.top - safeArea.bottom
//UIパーツ間の間隔
let margin_X = round(partsArea_W * 0.05)
let margin_Y = round(partsArea_H * 0.05)
//共通で使用するパーツの高さ幅など
let partsHeight = round(partsArea_H * 0.05)
let partsWidth = partsArea_W - margin_X * 2
let buttonHeight = round(partsArea_H * 0.05)
//lineNoLabelのサイズ、位置の設定
let lineNoLabel_W = partsWidth
let lineNoLabel_H = partsHeight
let lineNoLabel_X = safeArea.left + margin_X
let lineNoLabel_Y = safeArea.top + margin_Y
lineNoLabel.frame.size = CGSize(width: lineNoLabel_W, height: lineNoLabel_H)
lineNoLabel.frame.origin = CGPoint(x: lineNoLabel_X, y: lineNoLabel_Y)
//lineNoTFのサイズ、位置の設定
let lineNoTF_W = partsArea_W - margin_X * 2
let lineNoTF_H = partsHeight
let lineNoTF_X = safeArea.left + margin_X
let lineNoTF_Y = lineNoLabel.frame.maxY
lineNoTF.frame.size = CGSize(width: lineNoTF_W, height: lineNoTF_H)
lineNoTF.frame.origin = CGPoint(x: lineNoTF_X, y: lineNoTF_Y)
let doneButton_W = partsArea_W - margin_X * 2
let doneButton_H = buttonHeight
let doneButton_X = safeArea.left + margin_X
let doneButton_Y = view.bounds.height - safeArea.bottom - doneButton_H - margin_Y
doneButton.layer.cornerRadius = doneButton_H / 2
doneButton.frame.size = CGSize(width: doneButton_W, height: doneButton_H)
doneButton.frame.origin = CGPoint(x: doneButton_X, y: doneButton_Y)
}
//doneButtonが押されたときに呼ばれるメソッド
@objc func doneTaped(){
print("done")
//画面遷移
performSegue(withIdentifier: "goInput", sender: nil)
}
}
// MARK: - UITextFieldDelegate
extension LineViewController : UITextFieldDelegate{
//textFieldでReturnが押されたときに呼ばれる
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
//キーボードを閉じる
textField.resignFirstResponder()
}
//textFieldの編集が終わったときに呼ばれる
func textFieldDidEndEditing(_ textField: UITextField) {
guard let text = textField.text else { return }
print(text)
}
}