IBInspectable 变量值在界面生成器和模拟器中没有改变

IBInspectable variable value is not changing in interface builder and simulator

我正在创建自定义平行四边形视图,该视图使用默认偏移值渲染良好。但是当我从 ib 更改偏移值时它不起作用

@IBDesignable class CustomParallelogramView: UIView {


    @IBInspectable var offset: Float = 10.0

    var path = UIBezierPath()

    lazy var shapeLayer: CAShapeLayer = {
        let layer = CAShapeLayer()
        layer.path = path.cgPath
        return layer
    }()

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

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

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        drawParallelogram()
    }
    override func layoutSubviews() {
        super.layoutSubviews()
        updateFrame()
    }



    func drawParallelogram() {
        print(offset)
        path.move(to: CGPoint(x: bounds.minX + CGFloat(offset), y: bounds.minY))
        path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
        path.addLine(to: CGPoint(x: bounds.maxX - CGFloat(offset), y: bounds.maxY))
        path.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY))
        path.close()
        self.layer.mask = shapeLayer

    }

    func updateFrame() {
        shapeLayer.frame = bounds
    }

}

我更改了 IB 的偏移值,但它不会更改 IB 和模拟器

尝试:

@IBInspectable var offset: Float = 10.0 {
    didSet {
        drawParallelogram()
    }
}

几个想法:

  1. 正如丹尼尔所说,你真的想在你的 offset 观察者中调用 drawParallelgram

  2. 此外,在 layoutSubviews 中,您正在更新形状图层的 frame。您想要重置其 path 并再次更新您的面具。

  3. 您只是在 UIBezierPath 中添加了越来越多的笔划。你可能只是想让它成为一个局部变量,避免在现有路径上添加越来越多的笔画。

  4. prepareForInterfaceBuilder 暗示了对该方法的用途的一些误解。这不是为了在从 IB 启动时进行初始化。这是为了做一些特殊的配置,超出 init 方法已经完成的,IB 要求的。

    例如如果你有一个复杂的图表视图,稍后你将以编程方式提供真实的图表数据,但你想在 IB 中看到一些东西,尽管如此,你可能 prepareForInterfaceBuilder 填充一些虚拟数据,例如。但是你不应该重复你已经在 init 方法中完成的配置。

  5. 这里不相关(因为我会建议摆脱这些 init 方法),但是对于它的价值,如果我需要在 [=19] 期间进行配置=],我一般写两个init方法:

    override init(frame: CGRect = .zero) {
        super.init(frame: frame)
    
        <#call configure routine here#>
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    
        <#call configure routine here#>
    }
    

    请注意,在 init(frame:) 中,我还提供了默认值 .zero。这确保我涵盖了所有三种情况:

    • CustomView()
    • CustomView(frame:);或者
    • 如果故事板调用 CustomView(decoder:)

    简而言之,我以两个的价格获得三个init方法。哈哈


综上所述,您可以大大简化它:

@IBDesignable public class CustomParallelogramView: UIView {

    @IBInspectable public var offset: CGFloat = 10 { didSet { updateMask() } }

    override public func layoutSubviews() {
        super.layoutSubviews()
        updateMask()
    }

    private func updateMask() {
        let path = UIBezierPath()
        path.move(to: CGPoint(x: bounds.minX + offset, y: bounds.minY))
        path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
        path.addLine(to: CGPoint(x: bounds.maxX - offset, y: bounds.maxY))
        path.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY))
        path.close()

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = path.cgPath
        layer.mask = shapeLayer
    }
}