Swift 中的 self 类型及其在两阶段初始化中的使用

Mai*_*aux 1 initialization self swift

考虑以下代码,它将手势识别器添加到视图中。

class ViewController: UIViewController {
    @IBOutlet weak var imageView: UIImageView!

    let gesture = UITapGestureRecognizer(target: self, action: #selector(handleGesture(gesture:)))
    let test1 = self

    @objc func handleGesture(gesture: UITapGestureRecognizer) {
        // some code
        print("hello")
    }
    override func viewDidLoad() {
        let test2 = self
        super.viewDidLoad()
        imageView.addGestureRecognizer(gesture)
    }
}
Run Code Online (Sandbox Code Playgroud)

根据这个问题,上面的代码不起作用,因为我试图self在未完全初始化时使用(在手势识别器的初始化程序中),这是因为 Swift 的两阶段初始化。

我对简单的修复方法不感兴趣,但这会引发几个问题:

1)为什么编译器允许我们在self这里使用如果self还没有准备好使用?如果我试图self过早使用,我不应该得到编译器错误吗?

2)我们不能self在XCode中用alt+click直接检查的类型。但是,我们可以检查我的临时变量的类型test1和test2. 正如预期的那样,Whiletest2的类型是ViewController,test1的类型是(ViewController) -> () -> ViewController(即,一个接受 aViewController的闭包并返回一个不接受任何内容并返回 a 的闭包ViewController)。那是什么,为什么self在同一个类中有两种不同的类型?

OOP*_*Per 5

1)

如果我试图self过早使用,我不应该得到编译器错误吗?

我同意。您可以向swift.org发送错误报告。

为什么编译器允许我们在self这里使用ifself还没有准备好使用呢?

不幸的是,还有另一种self在的后裔NSObject,该方法self()的NSObject。

2)

那是什么,为什么 self 在同一个类中有两种不同的类型?

当前 Swift 在class上下文中解释初始值表达式,而不是在实例上下文中。

你知道方法名可以在 Swift 中用作闭包:

class ViewController: UIViewController {
    //..

    func aMethod() {
        //...
    }

    func anInstanceMethod() {
        let meth = aMethod // () -> ()
    }
}
Run Code Online (Sandbox Code Playgroud)

Swift 还可以在class上下文中引用一个实例方法,它会生成一个所谓的未应用方法引用(参见SE-0042),它当前返回一个柯里化函数:

class ViewController: UIViewController {
    //...

    func aMethod() {
        //...
    }

    class func aClassMethod() {
        let meth = aMethod // (ViewController) -> () -> ()
    }
}
Run Code Online (Sandbox Code Playgroud)

方法也self()一样。

通常我们不需要self()方法,我认为应该改变这种行为。