5

I have a simple class and I want to use keypath in the init, something like this:

class V: UIView {
    convenience init() {
        self.init(frame: .zero)
        self[keyPath: \.alpha] = 0.5
    }
}

let v = View()

When I run this code I get a runtime error:

Fatal error: could not demangle keypath type from ' ����XD':

But, if I specify the type in keyPath it works fine:

class V: UIView {
    convenience init() {
        self.init(frame: .zero)
        self[keyPath: \UIView.alpha] = 0.5
    }
}

let v = View()
print(v.alpha) \\ prints 0.5

But, what's even stranger is that this code works:

class V: UIView {
    convenience init() {
        self.init(frame: .zero)
        foo()
    }
    
    func foo() { 
        self[keyPath: \.alpha] = 0.5
    }
}

let v = View()
print(v.alpha) \\ prints 0.5

What is the actual reason for this error?

4

2 回答 2

9
于 2020-07-18T07:57:49.683 回答
0

这是因为方便 init(),方便初始化器是次要的,支持类的初始化器。您可以定义一个便利初始化程序,以从与便利初始化程序相同的类调用指定初始化程序,并将一些指定初始化程序的参数设置为默认值。

因为,在方便 init() 中,无法访问超类属性,所以您会收到致命错误:无法对 keypath 类型进行分解。

如果您在指定的 init() 中执行相同操作,它会工作,因为它确保超类已初始化。下面的代码将按预期打印 0.5:

  class View: UIView {
        init() {
            super.init(frame: .zero)
            self[keyPath: \.alpha] = 0.5
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }

    let v = View()
    print(v.alpha) // prints 0.5

在此处输入图像描述

于 2020-07-15T22:09:45.573 回答