我知道這個問題在這里被問了很多,我已經閱讀了所有這些問題,但我的問題仍然存在。我想在我的專案中包含委托模式,以便從一個類呼叫另一個類中的函式。但它在那里也不起作用。所以我創建了一個全新的專案來再次練習該模式。只有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 中呼叫一個函式,而不是我想對我的 buttonViewController 執行 segue。
這是我的 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)")
}
}
I've already tried to perform a segue that first viewDidLoad is called by my ButtonViewController, then to go back to the ViewController and then call the perform method again via a button to then see whether delegate is still nil, and yes it was unfortunately still nil.
Can somebody help me with this Problem?
Best regards!
uj5u.com熱心網友回復:
委托模式一開始讓很多人感到困惑。我發現我的大多數學生一開始都傾向于嘗試倒退,我認為這也是這里發生的事情。通常在委托模式中,有一個視圖控制器 (A) 呈現另一個 (B)。通常,B 上的某些操作應觸發 A 上的某些功能(在您的情況下,可能按下 B 上的按鈕會觸發 A 列印某些內容)。
在這種情況下,您將有兩個子類UIViewController:AViewController和BViewController和協議BViewControllerDelegate。它將設定如下:
- 該協議
BViewControllerDelegate將具有您想要AViewController在BViewController按下按鈕時呼叫的功能。 AViewController將符合此協議并實作此功能。- 在
BViewController你有你的委托屬性定義:weak var delegate: BViewControllerDelegate?。 - 在 的呈現期間,此屬性將在 的實體上
BViewController由AViewController自身的實體(的實體AViewController)設定BViewController。 - 的實體
BViewController將呼叫其委托屬性上的函式以回應按鈕按下。
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并設定了它的委托,但是這個新實體立即被釋放,因為它實際上并不是在其他任何地方使用的那個。
uj5u.com熱心網友回復:
協議/委托模式用于允許實體化的控制器(或其他物件)與創建它的類進行通信。
因此,在您的場景中,您希望ViewController符合ViewControllerDelegate... 當您實體化ButtonViewController(具有ViewControllerDelegate委托變數)時,您將其ButtonViewController委托給 self ( 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!")
}
}
編輯- 這是一個完整的運行示例。“主”視圖控制器有一個按鈕和一個標簽。點擊按鈕以顯示 ButtonVC。按鈕視圖控制器有一個文本欄位和一個“保存并關閉”按鈕。在文本欄位中輸入一些文本,點擊保存按鈕,文本將通過ViewControllerDelegate.
不需要@IBOutlet或不需要@IBAction連接——只需將一個空白視圖控制器的自定義類分配給ViewController:
// make ViewController conform to ViewControllerDelegate
class ViewController: UIViewController, ViewControllerDelegate {
let btn: UIButton = {
let v = UIButton()
v.setTitle("Show Button VC", for: [])
v.backgroundColor = .systemRed
v.setTitleColor(.white, for: .normal)
v.setTitleColor(.lightGray, for: .highlighted)
return v
}()
let label: UILabel = {
let v = UILabel()
v.backgroundColor = .green
v.numberOfLines = 0
v.text = "From ButtonVC:\n"
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
[label, btn].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
}
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
btn.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
btn.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
btn.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
label.topAnchor.constraint(equalTo: btn.bottomAnchor, constant: 20.0),
label.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
label.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
])
btn.addTarget(self, action: #selector(showButtonsVC(_:)), for: .touchUpInside)
}
@objc func showButtonsVC(_ sender: UIButton) {
// instantiate Button View Controller
let vc = ButtonViewController()
// set self as the delegate in ButtonViewController
vc.delegate = self
// present it
present(vc, animated: true, completion: nil)
}
func printTest(message: String) {
print("Delegate received:", message)
label.text = "From ButtonVC:\n" message
}
}
class ButtonViewController: UIViewController {
var delegate: ViewControllerDelegate?
let textField: UITextField = {
let v = UITextField()
v.borderStyle = .roundedRect
return v
}()
let btn: UIButton = {
let v = UIButton()
v.setTitle("Save and Close", for: [])
v.backgroundColor = .systemRed
v.setTitleColor(.white, for: .normal)
v.setTitleColor(.lightGray, for: .highlighted)
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemYellow
[textField, btn].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
}
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
textField.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
textField.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
textField.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
btn.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 20.0),
btn.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
btn.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
])
btn.addTarget(self, action: #selector(buttonTap(_:)), for: .touchUpInside)
}
@IBAction func buttonTap(_ sender: UIButton) {
// call the delegate
let str = textField.text ?? "No text entered..."
delegate?.printTest(message: str)
dismiss(animated: true, completion: nil)
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/362384.html
上一篇:如何防止ARSCNView旋轉
下一篇:用于協議比較的Swift解決方法
