当我尝试使用闭包作为 UIButton 的目标时出现奇怪的行为

Weird behavior when I try to use a closure as the target of a UIButton

我知道我需要将 let 关键字替换为 lazy var 才能访问 属性 否则我无法访问 'self'.

但是我发现 button.addTarget 可以构建成功,

为什么?通常,如果您尝试从需要成为惰性变量的闭包中访问 属性,对吗?

为了比较,testProperty 显示红色错误信息:

Cannot convert value of type (testController) -> () -> testController to specified type UITabBarController

import UIKit

class testController: UIViewController {
    
    let actionButton: UIButton = {
        let button = UIButton(type: .system)
        button.addTarget(self,  action: #selector(actionButtonTapped), for: .touchUpInside)
        return button
    }()
    
    let testProperty: UIViewController = {
        let obj: UIViewController = self
        return obj
    }()
    
    @objc func actionButtonTapped() {
        
    }
}

如果您检查 addTarget 签名,您将看到以下内容:

open func addTarget(_ target: Any?, action: Selector, for controlEvents: UIControl.Event)

第一个参数 targetAny?,因此将 (Function) 作为 target 编译正常。它甚至可以工作,但会导致奇怪的问题,比如打开键盘会阻止按钮调用 action.

您目前认为 self 指的是实例。

但不是,对于NSObject,它指的是this method的部分应用。实际上 运行 ViewController.self() 在实例化之前,例如在此关闭的上下文中,将使您的应用程序崩溃,但 self() 在 Xcode 13.3.

之前仍然显示为可用

截至目前,Swift 无法在不生成警告的情况下处理引用此方法。该警告告诉您使用 ViewController.self,其中 Swift 只能解释为元类型,而不是方法。它不明白发生了什么,但至少它告诉你你所做的是不正确的——方法实际上不是目标。

不管警告如何,我都Objective-C 不够了解,无法告诉您为什么发送到该方法的消息会向下传递到相关类型的实例。但是不要这样做。