当直接分配/实现 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)
}