[TIL] 2022-04-18


📌 AlertController


AlertControllerは、各選択をAlertActionと呼ぶユーザーにいくつかの選択を提供します.
AlertAction Style
  • default:デフォルト
  • キャンセル:選択を解除します.AlertControllerごとに1つしか使用できません.
  • 破壊
  • :この動作を選択することに注意してください.
  • AlertController Style
  • alert
    cancelボタンの位置は動作の数によって異なります.Actionは2個で左側,3個で最下端に位置する.
  • actionSheet
    actionの数にかかわらず、最下端に位置します.
  • [入力]ボタンを押すと、EメールまたはパスワードTextFieldにマウスを置くこともできます.UIalertActionの最後のパラメータHandlerモジュールには、ユーザーがこの操作を選択したときに実行するコードセットが含まれています.
    toBeFirstResponderパラメータは制御を受けるので、この制御をFirstResponderとするコードをモジュールに入れることができる.

    ▼▼AlertActionhandlerキャビネットを取り外す


    まず私たちを困らせている[弱toBeFirstResponder]を外して、コードを見てみましょう.
    let okAction: UIAlertAction 
    	= UIAlertAction(title: "입력하기",
                        style: UIAlertAction.Style.default) {(action: UIAlertAction) in 
                        	toBeFirstResponder?.becomeFirstResponder()}
    UIalertActionの最後のパラメータであるhandler
    UIalertActionをパラメータとし、戻りタイプはVoidエンクロージャです.
    ここで、リターンタイプは省略された行盤盤ケースです.
    UIAlertActionの定義部分に移動して確認すると,Handlerの定義が我々の推測であることがわかる.입력하기キーを押すと、このokactionは自分でhandlerの動作に移動します.しかし、私たちのコードはhandlerでこのactionを使用しません.toBeFirstResponderは、受信したコントロールをFirstResponderに変更するだけです.
    では、OKAction自身は本当にActionになるのでしょうか.確認してみましょう.もう1つのhandlerを関数alertHandlerとして取り,その関数でactionのtitleをチェックする.
    この関数をokActionとcancelActionのhandlerに渡すことで、コードを再使用し、呼び出しはselfです.alertHandler(:)を使用してもalertHandlerを使用しても、正常な動作が行われます.<<どうしたの???
    func alertHandler(_ alertAction: UIAlertAction) {
        guard let actionTitle = alertAction.title else {
            return
        }
        print("alertHandler >> \(actionTitle)")
    }
        
    private func showAlert(message: String, control toBeFirstResponder: UIControl?) {
        let alert: UIAlertController = UIAlertController(title: "알림",
                                                         message: message,
                                                         preferredStyle: UIAlertController.Style.alert)
            
        let okAction: UIAlertAction = UIAlertAction(title: "입력하기",
                                                    style: UIAlertAction.Style.default,
                                                    handler: self.alertHandler(_:))
            
        let cancelAction: UIAlertAction = UIAlertAction(title: "취소",
                                                        style: UIAlertAction.Style.cancel,
                                                        handler: alertHandler)
            
        alert.addAction(okAction)
        alert.addAction(cancelAction)
        
        self.present(alert, animated: true) {
            print("얼럿 화면에 보여짐")
        }
    }
    입력하기ボタンと취소ボタンを順番に押して、ログがよく撮れました.

    ループを参照


    次に、[flaktoBeFirstResponder]を追加した元のコードに戻ります.
    let okAction: UIAlertAction 
    	= UIAlertAction(title: "입력하기",
                        style: UIAlertAction.Style.default) { [weak toBeFirstResponder] (action: UIAlertAction) in 
                        	toBeFirstResponder?.becomeFirstResponder() }
    どうして弱者を使うのですか.ループ参照を事前に理解する必要があります.
    ARC(Automatic Reference Counting)
  • は、参照しないインスタンスをメモリから解放するために参照カウントを追跡する.
    循環参照
  • 相互参照、メモリを解放できません
  • ARCは、開発者のメモリ解放に対する負担を軽減することができるが、ちょっとした不注意により、
  • を循環参照する可能性がある.
    weak
  • は、このインスタンスの所有権を持たず、アドレス値のみを有するポインタ概念
  • である.
  • 自己参照インスタンスの参照カウント
  • は増加しない.
    >>https://babbab2.tistory.com/83この文章を精読!!<
    最終的に、「弱いtoBeFirstResponder」は、強い参照ループを防止するためのモジュールのキャプチャリストです.
    話がだいぶ漏れた.最初のコードスクリーンショットに戻ります.最後の行では、presentメソッドも後続のモジュールを使用します.すなわち、completionというパラメータにモジュールが追加されます.同様に、このモードのアニメーションを再生すると、実行するコードビームが追加されます.
    パラメータ名がhandlercompletionのほとんどは、エンクロージャを受け取ります.

    📌 JSONDecoder


    JSONファイルをAssetの使用に必要なクラスに登録します.
    のようなQuestions.jsonファイルをインポートします.
    項目でAssetにJSONファイルを登録する場合はデータセット拡張子を使用して挿入します.私たちのQuestions.datasetにはContents.jsonQuestions.jsonが含まれています.NSDataAssetクラスでは、このデータセットをコードからインポートおよび使用できます.
    Question.swift
    import Foundation
    import UIKit
    
    struct Question: Codable {
        let d: String
        let i: String
        let s: String
        let c: String
    }
    
    extension Question {
        static var all: [Question] = {
            guard let dataAsset: NSDataAsset = NSDataAsset(name: "Questions") else {
                return []
            }
            
            let jsonDecoder: JSONDecoder = JSONDecoder()
            
            do {
                return try jsonDecoder.decode([Question].self, from: dataAsset.data)
            } catch {
                return []
            }
        }()
    }
    all変数は「Question」配列を返す関数を格納します.この関数を見てみましょう.
    Assetをインポートする場合、ファイルが存在しない可能性がありますので、外部バインドは安全です.これをguard let 구문で実現した.Assetを安全にインポートする場合は、JSOndecoderインスタンスを作成し、decodeのfromパラメータに入れます. decode定義子から見るとthrowsによって実現される.復号中にエラーが発生する可能性があるため、decodeを使用する場合はtryを同時に書き込む必要があります.//https://babbab2.tistory.com/61