簡體   English   中英

Swift 委托模式:委托 = Nil

[英]Swift Delegate Pattern: Delegate = Nil

我知道這個問題在這里被問了很多,我已經閱讀了所有這些問題,但我的問題仍然存在。 我想在我的項目中包含委托模式,以便從一個 class 調用另一個 class 中的 function。 但它也沒有在那里工作。 所以我創建了一個全新的項目來再次練習該模式。 只有3個小時,我就是做不到。 我的委托仍然留在我的主 ViewController nil 中。

這是我的 ViewController 的代碼。 它是初始化的 ViewController 也是委托模式的主人,而 buttonViewController 是仆人:


import UIKit

protocol ViewControllerDelegate {
    func printTest(message: String)
}

class ViewController: UIViewController {
    
    var delegate: ViewControllerDelegate?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
    }
    

    @IBAction func perform(_ sender: UIButton) {
        let vc = storyboard?.instantiateViewController(withIdentifier: "vc") as! ButtonViewController
        if delegate == nil {
            print("Ist nil")
        }
        delegate?.printTest(message: "Test")
        present(vc, animated: true, completion: nil)
    }
    
}


如果用戶按下執行按鈕並且我想對我的 buttonViewController 執行 segue,我想在我的 buttonViewController 中調用 function。

這是我的 ButtonViewController:

import UIKit


class ButtonViewController: UIViewController, ViewControllerDelegate {


    override func viewDidLoad() {
        super.viewDidLoad()

        ViewController().delegate = self
        print("test")
        // Do any additional setup after loading the view.
    }

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */
    
    @IBAction func performsegue(_ sender: UIButton) {
        
    }
    
    func printTest(message: String) {
        print(message + "\(self)")
    }
}

我已經嘗試執行一個 segue,首先 viewDidLoad 由我的 ButtonViewController 調用,然后到 go 返回 ViewController,然后通過按鈕再次調用 perform 方法,然后查看委托是否仍然為零,是的,不幸的是它仍然是零。

有人可以幫我解決這個問題嗎?

此致!

委托模式一開始讓很多人感到困惑。 我發現我的大多數學生一開始都傾向於嘗試倒退,這也是我認為正在發生的事情。 通常在委托模式中有一個視圖 controller (A) 呈現另一個 (B)。 通常,對 B 的某些操作應在 A 上觸發一些 function (在您的情況下,可能按下 B 上的按鈕會觸發 A 打印某些內容)。

在這種情況下,您將擁有UIViewController的兩個子類: AViewControllerBViewController以及協議BViewControllerDelegate 它將設置如下:

  1. 當按下 BViewController 中的按鈕時,協議BViewControllerDelegate將具有您希望在BViewController上調用的AViewController
  2. AViewController將遵循此協議並實現此 function。
  3. BViewController中,您將定義您的委托屬性: weak var delegate: BViewControllerDelegate? .
  4. AViewController的呈現期間,此屬性將由BViewController的實例設置在BViewController的實例上( AViewController的實例)。
  5. BViewController的實例將在其委托屬性上調用 function 以響應按鈕按下。
class AViewController: UIViewController, BViewControllerDelegate {
    // This is 4, this segue action is invoked by a storyboard segue in the storyboard and is responsible for setting up the destination view controller and configuring it as needed (i.e., setting its delegate property)
    @IBSegueAction func makeBViewController(_ coder: NSCoder) -> BViewController {
        let bViewController = BViewController(coder: coder)!
        bViewController.delegate = self
        
        return bViewController
    }

    // Here we accomplish 2 (and also above where we declare conformance to the protocol)    
    func bViewControllerDidPerformAction(viewController: BViewController, message: String) {
        print(message)
    }
}
protocol BViewControllerDelegate: AnyObject {
    // Here we accomplish 1
    func bViewControllerDidPerformAction(viewController: BViewController, message: String)
}

class BViewController: UIViewController {
    // Here is 5
    @IBAction func buttonPressed(_ sender: Any) {
        delegate?.bViewControllerDidPerformAction(viewController: self, message: "Test Message")
    }
    
    // This is 3
    weak var delegate: BViewControllerDelegate?
}

我不是 100% 清楚你要在代碼中做什么,但我相信你的ViewController應該像AViewController一樣設置,而你的ButtonViewController應該像BViewController一樣設置。 此外,代碼行ViewController().delegate = self什么也不做,因為它創建了一個新的ViewController實例並設置了它的委托,但是這個新實例會立即被釋放,因為它實際上並不是在其他任何地方使用的那個。

協議/委托模式用於允許實例化的 controller(或其他對象)與創建它的 class 進行通信。

因此,在您的場景中,您希望ViewController符合ViewControllerDelegate ...當您實例化ButtonViewController (具有ViewControllerDelegate委托 var)時,您將該ButtonViewController的委托分配給自身( ViewController )。

現在, ButtonViewController可以通過它的delegate調用協議函數。

protocol ViewControllerDelegate {
    func printTest(message: String)
}

// make ViewController conform to ViewControllerDelegate
class ViewController: UIViewController, ViewControllerDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    
    @IBAction func perform(_ sender: UIButton) {
        let vc = storyboard?.instantiateViewController(withIdentifier: "vc") as! ButtonViewController
        
        // set self as the delegate in ButtonViewController
        vc.delegate = self
        
        present(vc, animated: true, completion: nil)
    }

    func printTest(message: String) {
        print("printTest in delegate:", message)
    }
    
}

class ButtonViewController: UIViewController {
    
    var delegate: ViewControllerDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()
        print("test")
    }
    
    @IBAction func buttonTap(_ sender: UIButton) {
        // call the delegate
        delegate?.printTest(message: "Sending to delegate!")
    }

}

在您的 ViewController 中覆蓋prepare(for segue: UIStoryboardSegue, sender: Any?)並像這樣修改

    guard let btnVC = segue.destination as? ButtonViewController else {
     return
    }
    btnVC.delegate = self
}

現在您已經設置了對您的 delegate.try 的引用並運行

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM