如何在另一个类中读取和设置变量?

时间:2020-05-12 00:00:58

标签: ios swift

在搜索中,我看到这是一个常见问题,但是我尝试了一些解决方案,但仍无法解决。下面是一个简单的例子。当我运行该应用程序并按按钮时,将按预期打印0。按下button2之后,也按预期打印按钮1。如果我移动选择器,然后按按钮,我希望是2,但仍然是1。

我收集到这是因为ViewController()。sample()正在创建一个副本,而实际上并未更改“原始” ViewController()中的变量。我为需要重新配置以获得所需的行为而感到困惑。

import UIKit

class pickerHelper: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {

    let data: [String]
    init(data: [String]) {
        self.data = data
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        1
    }
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        data.count
    }
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        data[row]
    }
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        ViewController().sample()
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        p1.delegate = helper1
        p1.dataSource = helper1
    }

    @IBOutlet weak var p1: UIPickerView!

    let helper1 = pickerHelper(data:["a", "b", "c"])
    var test = Int()

    @IBAction func button(_ sender: Any) {
        print(test)
    }

    @IBAction func button2(_ sender: Any) {
        test = 1
    }

    func sample() {
        test = 2
    }
}

2 个答案:

答案 0 :(得分:1)

在这种情况下,您将使用委托模式或回调闭包;后者更“迅速”。

有代表团:

protocol PickerHelperDelegate {
    func pickerHelper(_ helper: selectedRow row:)
}

然后在您的PickerHelper中添加一个委托属性,并在需要时调用该委托:

class PickerHelper: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {

    let data: [String]

    var delegate: PickerHelperDelegate? 

    init(data: [String]) {
        self.data = data
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        1
    }
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        data.count
    }
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        data[row]
    }
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        self.delegate?.pickerHelper(self, selectedRow: row)
    }
}

在视图控制器中,您需要分配委托并实现协议功能:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        p1.delegate = helper1
        p1.dataSource = helper1
        helper1.delegate = self // Assign this object as the picker helper's delegate
    }

    @IBOutlet weak var p1: UIPickerView!

    let helper1 = pickerHelper(data:["a", "b", "c"])
    var test = Int()
}

extension ViewController: PickerHelperDelegate {
    func pickerHelper(_ helper: PickerHelper, selectedRow row:Int) {
        self.sample()
        print("Selected row \(row)")
    }
}

您可以使用闭包执行类似的操作:

class PickerHelper: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {

    let data: [String]

    var changeHandler: ((Int)->Void)? 

    init(data: [String]) {
        self.data = data
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        1
    }
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        data.count
    }
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        data[row]
    }
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        self.changeHandler?(row)
    }
}

在视图控制器中,您需要为changeHandler属性分配一个闭包:

override func viewDidLoad() {
     super.viewDidLoad()
     // Do any additional setup after loading the view.
     p1.delegate = helper1
     p1.dataSource = helper1
     helper.changeHandler = { row in 
         self.sample()
         print("Selected row \(row)")
    }
}

您还可以更改协议或闭包以传回data元素,而不只是行号,并为PickerHelper使用泛型,这样它不仅限于字符串。

请注意,类按约定以大写字母开头,因此您应该说PickerHelper,而不是pickerHelper

答案 1 :(得分:0)

您可以使用static属性将其状态保留在类中。

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        p1.delegate = helper1
        p1.dataSource = helper1
    }

    @IBOutlet weak var p1: UIPickerView!

    let helper1 = pickerHelper(data:["a", "b", "c"])
    static var test = Int()

    @IBAction func button(_ sender: Any) {
        print(test)
    }

    @IBAction func button2(_ sender: Any) {
        ViewController.test = 1
    }

    static func sample() {
        test = 2
    }
}