Swift自定义UIView初始化时自定义属性传值为nil如何解决
问题原因
打印得到nil是Swift初始化调用顺序导致的,核心逻辑如下:
convenience init(colorOfGradient:)属于便利构造器,按照Swift构造规则,便利构造器必须先调用当前类的指定构造器,也就是你代码里的init(frame:)- 执行
self.init(frame: CGRect.zero)时会立刻进入override init(frame:)的方法实现,此时还没执行self.colorOfGradient = colorOfGradient的赋值逻辑,colorOfGradient还是默认的nil,打印自然拿不到值 - 等
init(frame:)执行完毕回到便利构造器,才会给colorOfGradient属性赋值,但这时候init(frame:)里的打印代码早就运行结束了。
另外你当前代码还漏了UIView子类必须实现的required init?(coder:)构造器,会触发编译报错。
修复方案
你可以根据自己的代码习惯选下面任意一种方案:
方案1:拆分UI配置逻辑,把依赖自定义属性的逻辑挪到赋值后执行
保留现有便利构造器的写法,把不依赖自定义属性的基础UI配置放在init(frame:)里,依赖colorOfGradient的逻辑等属性赋值完成后再调用,参考实现:
class WarningView: UIView { var colorOfGradient: String? convenience init(colorOfGradient: String?) { self.init(frame: .zero) self.colorOfGradient = colorOfGradient // 所有依赖colorOfGradient的逻辑,放在赋值后执行 setupGradientStyle() } override init(frame: CGRect) { super.init(frame: frame) // 这里只做不依赖自定义参数的基础配置 setupBaseConfig() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupBaseConfig() { // 比如设置统一的圆角、遮罩、子视图约束这类通用逻辑 } private func setupGradientStyle() { print(colorOfGradient as Any) // 此处可正确拿到传入的"red" // 编写渐变层的绘制、颜色配置逻辑 } }
方案2:自定义指定构造器,初始化时优先给自定义属性赋值
如果需要在构造方法内部就拿到colorOfGradient的值做配置,可以直接自定义指定构造器,给frame参数加默认值,既不影响原有调用方式,还能保证属性在调用父类构造器前就完成赋值:
class WarningView: UIView { var colorOfGradient: String? // 给frame参数加默认值.zero,调用时可以不传frame init(frame: CGRect = .zero, colorOfGradient: String?) { // 先给当前类的自定义属性赋值 self.colorOfGradient = colorOfGradient // 再调用父类的指定构造器 super.init(frame: frame) print(self.colorOfGradient as Any) // 此处可正确打印传入的"red" // 可以直接在这里编写所有依赖colorOfGradient的配置逻辑 } override init(frame: CGRect) { super.init(frame: frame) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
这个方案下你原来的调用代码WarningView(colorOfGradient: color)不需要做任何修改,编译器会自动匹配到这个带默认参数的构造器。
内容的提问来源于stack exchange,提问作者fonzyara
相关产品推荐
相关产品推荐

