简体   繁体   English

UIView init 覆盖导致 IBDesignable 崩溃

[英]UIView init override causes IBDesignable to crash

I have a very strange problem with XCode 7.1 interface builder.我对 XCode 7.1 界面构建器有一个非常奇怪的问题。 I have a really simple UIView subclass, which renders fine in storyboard editor :我有一个非常简单的 UIView 子类,它在故事板编辑器中呈现良好

import UIKit

@IBDesignable
class DashboardHeaderView: UIView {

    @IBInspectable
    var maskClipHeight: CGFloat = 40.0

    override func layoutSubviews() {
        super.layoutSubviews()
        self.setMask()
    }

    private func setMask() {
        let mask = CAShapeLayer()
        mask.path = self.createMaskPath()
        self.layer.mask = mask
    }

    private func createMaskPath() -> CGPath {
        let maskPath = UIBezierPath()
        maskPath.moveToPoint(CGPoint(x: bounds.minX, y: bounds.minY))
        maskPath.addLineToPoint(CGPoint(x: bounds.maxX, y: bounds.minY))
        maskPath.addLineToPoint(CGPoint(x: bounds.maxX, y: bounds.maxY - self.maskClipHeight))
        maskPath.addLineToPoint(CGPoint(x: bounds.minX, y: bounds.maxY))
        maskPath.closePath()

        return maskPath.CGPath
    }

}

However, if I only add initializer override to it:但是,如果我只向它添加初始化程序覆盖:

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

It fails with errors:它失败并出现错误:

  • error: IB Designables: Failed to update auto layout status: The agent crashed错误:IB Designables:无法更新自动布局状态:代理崩溃
  • error: IB Designables: Failed to render instance of DashboardHeaderView: The agent crashed错误:IB Designables:无法呈现 DashboardHeaderView 的实例:代理崩溃

I am 100% certain that that initializer override makes it crash as I've reproduced it a couple of times.我 100% 确定该初始化程序覆盖使它崩溃,因为我已经复制了几次。 If I only comment it out, it works again.如果我只注释掉它,它会再次起作用。

Anyone has any idea why this is happening and if there is a way to fix/workaround it?任何人都知道为什么会发生这种情况,以及是否有办法修复/解决它?

I've been struggling with this all day.我一整天都在为此苦苦挣扎。 You need to implement:您需要实施:

override init(frame: frame) {
    super.init(frame: frame)
}

That's the initializer the IBDesignable agent uses to instantiate the class.这是 IBDesignable 代理用来实例化类的初始化程序。 So, in my case I had another initializer as well.所以,就我而言,我还有另一个初始化程序。

init(frame: CGRect, maxValue: Double, minValue: Double) {
    super.init(frame: frame)

    self.maxValue = maxValue
    self.minValue = minValue
}

My init was blocking the init that IBDesignable needs.我的 init 阻塞了 IBDesignable 需要的 init。 Once I overrode the default init as above I had the choice of leaving my init as is or converting it to a convenience init:一旦我像上面一样覆盖了默认的 init,我就可以选择保持我的 init 原样或将其转换为方便的 init:

convenience init(frame: CGRect, maxValue: Double, minValue: Double) {
    self.init(frame: frame)

    self.maxValue = maxValue
    self.minValue = minValue
}

Now I can add some default behavior for IBDesigner:现在我可以为 IBDesigner 添加一些默认行为:

var initForIB = false

init(frame: CGRect, maxValue: Double, minValue: Double) {
    super.init(frame: frame)

    self.maxValue = maxValue
    self.minValue = minValue
    initForIB = false
}

override init(frame: CGRect) {
    super.init(frame: frame)
    initForIB = true
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func drawRect(rect: CGRect) {
    if initForIB {
        initIBDefaults()
    }
    // ...do some other stuff...
}

我遇到了类似的问题,发现在 prepareForInterfaceBuilder() 函数之外为 ibdesignable 视图设置掩码会导致渲染崩溃……prepareForInterfaceBuilder() 不是从系统调用的,而是由 interfaceBuilder 调用的,因此您需要设置此处和awakeFromNib() 中的maskView。

I've found the answer on another SO page: @IBDesignable crashing agent我在另一个 SO 页面上找到了答案: @IBDesignable crashing agent

You need to override both init(frame:) and init?(coder:) .您需要覆盖init(frame:)init?(coder:) If you override only one of the two, IB rendering will crash.如果仅覆盖两者之一,IB 渲染将崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM