[英]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
的兩個子類: AViewController
和BViewController
以及協議BViewControllerDelegate
。 它將設置如下:
BViewControllerDelegate
將具有您希望在BViewController
上調用的AViewController
。AViewController
將遵循此協議並實現此 function。BViewController
中,您將定義您的委托屬性: weak var delegate: BViewControllerDelegate?
.AViewController
的呈現期間,此屬性將由BViewController
的實例設置在BViewController
的實例上( AViewController
的實例)。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.