Как получить доступ к переменной класса внутри замыкания? - PullRequest
0 голосов
/ 14 ноября 2018

Я читал эту тему: Свифт, обращающийся к переменной класса внутри замыканий . Но не помогает мне.

Задача

У меня есть ViewControllerData для отображения данных и другие ViewControllerEdit для редактирования данных. Я хочу отправить объект из ViewControllerData в ViewControllerEdit, я делаю это с performSegue, но я не могу получить отредактированный объект из ViewControllerEdit. Я хочу передать его закрытие (funcReturnFromEdit) как параметр в prepare функции.

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 голосов
/ 14 ноября 2018

Вы должны объявить завершение завершения в 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
            }
        }
    }
}

Из соображений безопасности я рекомендую также использовать shouldPerformSegue для подавления перехода, если saleOrder равно nil

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

Примечание: пожалуйста, не используйте уродливый target-c-ish copy() в Свифте

0 голосов
/ 14 ноября 2018

Если вам нужно использовать глобальную переменную / метод в закрытии, поставьте self. перед вашей переменной / методом

Так что вы можете заменить это

saleOrder = saleEdited

на

self.saleOrder = saleEdited

но похоже, что проблема тоже где-то еще.Вам просто нужно передать saleOrder из первого во второй ViewController, где вы его редактируете, а затем передать данные обратно в первый контроллер представления

Итак, сначала удалите ненужный код из 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
            }
        }
    }
}
...