作为类属性的快速闭包无法访问其他类属性



当直接分配/实现 Swift 闭包时,访问类属性是没有问题的。但是当我尝试将闭包也定义为类属性时,无法访问其他类属性。这是为什么呢?


下面是一个示例:

虽然直接分配给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)
}
}

原因:

在完成类型的初始化过程之前,无法访问self

在您的代码中,editorCompletionBlock是一个存储属性,你尝试访问其中的self.tableView。这就是它给出编译时错误的原因。

溶液:

相反,editorCompletionBlock作为lazy属性来使其正常工作。

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

解决方案 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)
}

最新更新