如何在闭包内部访问类的变量?

时间:2018-11-14 12:06:08

标签: ios swift function closures

我阅读了以下主题:Swift accessing class variable inside closures。但是对我没有帮助。

问题

我有一个ViewControllerData用于显示数据,另外一个ViewControllerEdit用于编辑数据。我想将对象从ViewControllerData发送到ViewControllerEdit,我用performSegue做到了,但是我无法从ViewControllerEdit获取编辑后的对象。我想像prepare函数中的参数一样传递闭包(funcReturnFromEdit)。

class ViewControllerData: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var tableViewData: UITableView!
    var saleOrder : SaleOrder?  // THIS! <--------

    // In this closure I want take the edited object.
    let funcReturnFromEdit = { (saleEdited : SaleOrder) -> () in
        self.saleOrder = saleEdited // I can't do this. Error: Value of type '(ViewControllerData) -> () -> (ViewControllerData)' has no member 'saleOrder'
    }

    ....

      override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        segue.identifier == "segueEditOrder" {
        let editVc = segue.destination as! ViewControllerEdit
        if saleOrder != nil {
            editVc.saleOrderToEdit = saleOrder!.copy() as! SaleOrder
        }
        editVc.funcReturn = self.funcReturnFromEdit // <-- Not works
    }
}

错误是:Instance member 'saleOrder' cannot be used on type 'ViewControllerData '

此外,我不知道如何在ViewControllerEdit上创建此功能

class ViewControllerEdit: UIViewController, UITableViewDelegate, UITableViewDataSource {

    var saleOrderToEdit : SaleOrder?

    var funcReturn = { (SaleOrder) -> Void in {} } // <- This not compile. How to do this?

    ...
    /*
     Funcs to make edition...
    */

    func endEditions() {
        funcReturn(saleOrderToEdit) // <- Here I want send to back ViewControllerData
    }
}

2 个答案:

答案 0 :(得分:2)

如果需要在闭包中使用全局变量/方法,请将self.放在变量/方法之前

因此您可以替换

saleOrder = saleEdited

使用

self.saleOrder = saleEdited

,但看起来问题也出在其他地方。您只需要将saleOrder从第一个传递到第二个ViewController,然后在其中进行编辑,然后将数据传递回第一个View Controller

因此,首先从ViewControllerData中删除不必要的代码:

let funcReturnFromEdit = { (saleEdited : SaleOrder) -> () in
    saleOrder = saleEdited // I can't do this. 
}

并在ViewControllerEdit替换中修复完成处理程序

var funcReturn = { (SaleOrder) -> Void in {} }

var funcReturn : ((SaleOrder) -> ())?

还可以编辑endEditions方法,因为funcReturn是可选的

func endEditions() {
    funcReturn?(saleOrderToEdit)
}

现在,您只需在ViewControllerData修复prepare方法中设置当用户从funcReturn调用ViewControllerEdit时应该执行的操作

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "segueEditOrder" {
        let editVc = segue.destination as! ViewControllerEdit
        if let saleOrderToPass = saleOrder {
            editVc.saleOrderToEdit = saleOrderToPass
            editVc.funcReturn = { saleEdited in
                self.saleOrder = saleEdited //This code is executed when you call funcReturn?(saleOrderToEdit) from ViewControllerEdit
            }
        }
    }
}

答案 1 :(得分:1)

您必须在ViewControllerEdit中声明完成关闭并在endEditions中调用

class ViewControllerEdit: UIViewController, UITableViewDelegate, UITableViewDataSource {

    var saleOrderToEdit : SaleOrder!

    var editCompletion : ((SaleOrder)->())?

...

    func endEditions() {
        editCompletion?(saleOrderToEdit)
    }

ViewControllerData prepare(for中指定闭包

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "segueEditOrder" {
        let editVc = segue.destination as! ViewControllerEdit
        if let saleOrderToEdit = saleOrder {
            editVc.saleOrderToEdit = saleOrderToEdit
            editVc.editCompletion = { [weak self] saleEdited in 
                self?.saleOrder = saleEdited
            }
        }
    }
}

出于安全原因,如果shouldPerformSeguesaleOrder,我建议也实施nil来抑制伪装

func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
    return saleOrderToEdit != nil
}

注意:请不要在Swift中使用难看的 objective-c-ish copy()