Swift中的自我类型及其在两阶段初始化中的使用
考虑下面的代码,它将手势识别器添加到视图中Swift中的自我类型及其在两阶段初始化中的使用,swift,initialization,self,Swift,Initialization,Self,考虑下面的代码,它将手势识别器添加到视图中 class ViewController: UIViewController { @IBOutlet weak var imageView: UIImageView! let gesture = UITapGestureRecognizer(target: self, action: #selector(handleGesture(gesture:))) let test1 = self @objc func han
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)
}
}
根据,上述代码不起作用,因为我试图在未完全初始化时使用self
(在手势识别器的初始值设定项中),这是因为Swift的两阶段初始化
我对简单的解决方案不感兴趣,但这引发了几个问题:
1) 如果self
还没有准备好使用,为什么编译器允许我们在这里使用self
?如果我试图过早地使用self
,是否应该出现编译器错误
2) 我们不能直接用alt+点击XCode来检查self
的类型。但是,我们可以检查特殊变量的类型test1
和test2
。虽然test2
的类型是ViewController
,但正如预期的那样,test1
的类型是(ViewController)->()->ViewController
(即,接受ViewController
并返回不接受任何内容并返回ViewController
的闭包)。这是什么?为什么同一个类中有两种不同的类型
如果我试图过早地使用self
,是否应该出现编译器错误?
我同意。你可以发一封信
如果self
未准备好使用,编译器为什么允许我们在此处使用self
不幸的是,在NSObject
的后代中还有另一个self
(二)
这是什么?为什么self在同一个类中有两种不同的类型?
当前Swift在类
上下文中解释初始值表达式,而不是在实例上下文中
您知道,方法名称可以用作Swift中的闭包:
class ViewController: UIViewController {
//..
func aMethod() {
//...
}
func anInstanceMethod() {
let meth = aMethod // () -> ()
}
}
Swift还可以引用类
上下文中的实例方法,该方法生成所谓的未应用方法引用(请参阅),该引用当前返回一个curried函数:
class ViewController: UIViewController {
//...
func aMethod() {
//...
}
class func aClassMethod() {
let meth = aMethod // (ViewController) -> () -> ()
}
}
方法self()
也是如此
通常我们不需要self()
方法,我认为应该改变这种行为。1)
如果我试图过早地使用self
,是否应该出现编译器错误?
我同意。你可以发一封信
如果self
未准备好使用,编译器为什么允许我们在此处使用self
不幸的是,在NSObject
的后代中还有另一个self
(二)
这是什么?为什么self在同一个类中有两种不同的类型?
当前Swift在类
上下文中解释初始值表达式,而不是在实例上下文中
您知道,方法名称可以用作Swift中的闭包:
class ViewController: UIViewController {
//..
func aMethod() {
//...
}
func anInstanceMethod() {
let meth = aMethod // () -> ()
}
}
Swift还可以引用类
上下文中的实例方法,该方法生成所谓的未应用方法引用(请参阅),该引用当前返回一个curried函数:
class ViewController: UIViewController {
//...
func aMethod() {
//...
}
class func aClassMethod() {
let meth = aMethod // (ViewController) -> () -> ()
}
}
方法self()
也是如此
通常我们不需要
self()
方法,我认为应该改变这种行为。这是一种有趣的行为,适用于Objective-C对象。让我们举三个例子:
class Object: NSObject {
let test = self // compiles
}
class NonNSObject {
// let test = self // errors
lazy var lazyTest = self // compiles
}
struct NonClass {
// let test = self // errors
lazy var lazyTest = self // errors
}
NonNSObject
展示了您可以逃避的东西:
对象在完全初始化之前无法引用自身,并且let
绑定必须在完全初始化之前全部初始化,因此此操作失败
然而,NSObject恰好有一个Objective-C方法-(instancetype)self代码>返回self。我们可以在非NSObject上对此进行建模,如下所示:
func returnSelf() -> NonNSObject {
return self
}
这就是我们开始看到2)答案的地方
如果我们在类上引用这个方法returnSelf
,我们就会得到签名(NonNSObject)->()->NonNSObject
。您可以使用任何实例方法执行此操作,如下所示:
let test = NonNSObject.returnSelf
在这种情况下,签名是有意义的:
参数是我们实际想要调用方法的对象
然后我们“应用”函数(在本例中,没有参数)
我们最终得到了回报值
让curriedFunction=NonNSObject.returnSelf/(Self)->()->Self
让readyToCall=curriedFunction(NonNSObject())/()->Self
让finallyApplied=readyToCall()//Self
把所有的部分放在一起,我们可以看到,在ViewController(从UIViewController继承,从NSObject继承)的情况下,有一个实例方法self
,编译器认为这是您的意思,所以它使用它而不是实例本身(因为这将是一个错误)。因此,它的签名是在类本身上使用实例方法的自然结果。它需要一个实例,这是第一个参数
总之:
1) Swift编译器在NSObject上找到一个函数self
,并返回当前格式,而不是假设您出错。
2) 这是函数的货币形式,尤其是返回自己类型的实例方法。
2.5)它仍然以粉红色突出显示,因为Swift ObjC interop有点粗糙,self
既是一种方法,也是一种self
另外,结构根本无法引用自身,即使是懒洋洋的 这是适用于Objective-C对象的有趣行为。让我们举三个例子:
class Object: NSObject {
let test = self // compiles
}
class NonNSObject {
// let test = self // errors
lazy var lazyTest = self // compiles
}
struct NonClass {
// let test = self // errors
lazy var lazyTest = self // errors
}
NonNSObject
展示了您可以逃避的东西:
对象在完全初始化之前无法引用自身,并且let
绑定必须在完全初始化之前全部初始化,因此此操作失败
然而,NSObject恰好有一个Objective-C方法-(instancetype)self代码>返回self。我们可以在非NSObject上对此进行建模,如下所示:
func returnSelf() -> NonNSObject {
return self
}
这是w