Swift:以编程方式通过委派更改另一个 ViewController 的值

Swift: Change value of another ViewController with delegation programmatically

我正在尝试通过单击第二个 ViewController 中的一个按钮来更改一个 ViewController 的值。 但到目前为止,它只打印了一条消息,并没有改变值。

我有这个 class 我在其中定义了一个视图:

class CounterView: UIView {

    public var creditPointValue = Int()

    let label = UILabel()


    override init(frame: CGRect) {
        super.init(frame: frame)
        self.translatesAutoresizingMaskIntoConstraints = false
        backgroundColor = .cyan

        self.addSubview(label)
        label.text = "Credit Points: \(creditPointValue)"
        label.translatesAutoresizingMaskIntoConstraints = false;
        label.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
        label.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true

    }

    func changeCreditPointValue(value:Int){
        creditPointValue = creditPointValue + value
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

我在这个 ViewController 中使用那个视图,我想操纵变量 "creditPointValue":

protocol AddCreditsDelegate {
    func addCreditsToCounter()
}

class ViewController: UIViewController {

    var delegate: AddCreditsDelegate?

    var counterView = CounterView()

    let label = UILabel()

    let button = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        view.backgroundColor = .white

        view.addSubview(button)
        button.backgroundColor = .red
        button.setTitle("View2", for: .normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.addTarget(self, action: #selector(changeView), for: .touchUpInside)
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    }

    override func viewDidAppear(_ animated: Bool) {
        view.addSubview(counterView)
        counterView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        counterView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        counterView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        //counterView.frame.size.height = 30
        counterView.bottomAnchor.constraint(equalTo: counterView.topAnchor, constant: 50).isActive = true


    }

    @objc func changeView(){
        delegate?.addCreditsToCounter()
        navigationController?.pushViewController(ViewController2(), animated: true)
    }
}

在这一秒内 ViewController 我试图通过单击我添加到视图中的按钮来更改值:

class ViewController2: UIViewController {

    let button = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        view.addSubview(button)
               button.backgroundColor = .red
               button.setTitle("add Credits", for: .normal)
               button.translatesAutoresizingMaskIntoConstraints = false
               button.addTarget(self, action: #selector(addCreditsButton), for: .touchUpInside)
               button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
               button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    }

    @objc func addCreditsButton(){
        addCreditsToCounter()
    }    
}

extension ViewController2 : AddCreditsDelegate{
    func addCreditsToCounter() {
        let vc = ViewController()
        vc.delegate = self
        vc.counterView.creditPointValue += 5
        print("pressed")
    }
}

到目前为止,每次我单击按钮时只打印消息 "pressed",我什至不知道我尝试使用委托的方法是否朝着正确的方向前进。

您在这里创建一个新实例

  let vc = ViewController()

相反你需要

@objc func changeView() {  
 let sec = ViewController2(),
 sec.delegate = self
 navigationController?.pushViewController( animated: true)
}

然后在SecondVC中声明这个

weak var delegate:ViewController?

终于

    func addCreditsToCounter() {  
        delegate?.counterView.creditPointValue += 5
        print("pressed")
    }

您不应该在每次调用 ViewController2.addCreditsToCounter 时都创建一个新的 ViewController 实例,您已经有一个 ViewController 在 [=18= 中创建了一个 ViewController2 实例].只需使用委托在 ViewController2 中存储对 ViewController 的弱引用。在这种情况下 ViewController(不是 ViewController2)应该符合 AddCreditsDelegate。 首先,替换

protocol AddCreditsDelegate {
    func addCreditsToCounter()
}

protocol AddCreditsDelegate: AnyObject {
    func addCreditsToCounter()
}

然后将 weak var delegate: AddCreditsDelegate? 添加到 ViewController2 并删除 ViewController.delegate。去掉ViewController2.addCreditsToCounterViewController2应该不符合AddCreditsDelegate。这意味着在 ViewController2.addCreditsButton 中你应该调用 delegate?.addCreditsToCounter(),而不是 addCreditsToCounter()

ViewController 应该符合 AddCreditsDelegate:

extension ViewController: AddCreditsDelegate {
    func addCreditsToCounter() {
        counterView.creditPointValue += 5
        print("pressed")
    }
}

并且不要忘记初始化 ViewController2.delegate。将您的 ViewController.changeView 实施替换为

let controller = ViewController2()
controller.delegate = self
navigationController?.pushViewController(controller, animated: true)