Определение закрытия Swift, поскольку свойство класса не может получить доступ к другим свойствам класса - PullRequest
0 голосов
/ 23 января 2020

При непосредственном назначении / реализации замыкания Swift нет проблем с доступом к свойствам класса. Но когда я пытаюсь определить замыкание как свойство класса ie, доступ к другим свойствам класса невозможен. Почему это так?


Вот пример:

Хотя замыкание, непосредственно назначенное editorVC.completionBlock, может получить доступ к свойству класса tableView без проблем, тот же код внутри приводит к ошибке, когда замыкание определяется как свойство класса editorCompletionBlock:

class MyViewController: UIViewController {
    @IBOutlet var tableView: UITableView!

    func showEditor(withData: String) {
        let editorVC = EditorViewController()

        // Directly assign closure - Works without any problem
        editorVC.completionBlock = { (result) in
            self.tableView.reloadData()
            doSomething(withResult: result)
            // ...
        }
        present(editorVC, animated: true, completion: nil)
    }

    // Define closure as class property ==> Error
    let editorCompletionBlock: EditorCompletionBlock = { (resut) in
        // ERROR: Value of type '(MyViewController) -> () -> MyViewController' has no member 'tableView'
        self.tableView.reloadData()
        doSomething(withResult: result)
        // ...
    }
}


typealias EditorCompletionBlock = (String) -> Void

class EditorViewController: UIViewController {
    var completionBlock: EditorCompletionBlock?

    func closeEditor(withResult result: String) {
        completionBlock?(result)
    }
}

Ответы [ 2 ]

3 голосов
/ 23 января 2020

Причина:

Вы не можете получить доступ к self, пока не завершится процесс инициализации типа.

В вашем коде editorCompletionBlock является хранимым свойством , и вы пытаетесь получить доступ к self.tableView внутри него. По этой причине выдается ошибка времени компиляции.

Решение:

Вместо этого сделайте editorCompletionBlock в качестве свойства lazy, чтобы это работало.

lazy var editorCompletionBlock: EditorCompletionBlock = { (result) in
    self.tableView.reloadData()
    doSomething(withResult: result)
}
1 голос
/ 23 января 2020

Решение 1:

поместите editorCompletionBlock в viewDidLoad (: _) , и оно должно работать как шарм:

    class MyViewController: UIViewController {

        @IBOutlet var tableView: UITableView!

        func showEditor(withData: String) {
            let editorVC = EditorViewController()

            editorVC.completionBlock = { (result) in
                self.tableView.reloadData()
            }
            present(editorVC, animated: true, completion: nil)
        }

        override func viewDidLoad() {
            super.viewDidLoad()
            let editorCompletionBlock: EditorCompletionBlock = { (resut) in
                self.tableView.reloadData() ///should work :)
            }
        }

    }


    typealias EditorCompletionBlock = (String) -> Void

    class EditorViewController: UIViewController {
        var completionBlock: EditorCompletionBlock?

        func closeEditor(withResult result: String) {
            completionBlock?(result)
        }
    }

Решение 2: Или вы можете просто объявить свое закрытие как lazy:

lazy var editorCompletionBlock: EditorCompletionBlock = { (result) 
      in
    self.tableView.reloadData()
    doSomething(withResult: result)
}
...