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

azh*_*har 2 uiview swift ibinspectable

我正在创建自定义平行四边形视图,并且视图使用默认偏移值渲染得很好。但是当我改变 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
    }

}
Run Code Online (Sandbox Code Playgroud)

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

Rob*_*Rob 5

有几点想法:

\n\n
    \n
  1. 正如丹尼尔所说,你真的想召集drawParallelgram你的offset观察员。

  2. \n
  3. 另外,在 中layoutSubviews,您\xe2\x80\x99 正在更新frame形状图层的 。您想重置它path并再次更新您的面具。

  4. \n
  5. 您\xe2\x80\x99 只是向您的UIBezierPath. 您可能只想将其设为局部变量,并避免向现有路径添加越来越多的笔划。

  6. \n
  7. prepareForInterfaceBuilder表明人们对这种方法的目的存在一些误解。这是\xe2\x80\x99t,用于从 IB 启动时进行初始化。这是为了进行一些特殊的配置,超出了initIB 所要求的方法已经完成的配置。

    \n\n

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

  8. \n
  9. 它\xe2\x80\x99s在这里不相关(因为我\xe2\x80\x99m会建议摆脱这些init方法),但是对于它\xe2\x80\x99s的价值,如果我需要在期间进行配置init,我一般写两个init方法:

    \n\n
    override init(frame: CGRect = .zero) {\n    super.init(frame: frame)\n\n    <#call configure routine here#>\n}\n\nrequired init?(coder aDecoder: NSCoder) {\n    super.init(coder: aDecoder)\n\n    <#call configure routine here#>\n}\n
    Run Code Online (Sandbox Code Playgroud)\n\n

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

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

    简而言之,我用init两种方法的价格得到了三种方法。哈哈。

  10. \n
\n\n
\n\n

话虽如此,您可以大大简化这一点:

\n\n
@IBDesignable public class CustomParallelogramView: UIView {\n\n    @IBInspectable public var offset: CGFloat = 10 { didSet { updateMask() } }\n\n    override public func layoutSubviews() {\n        super.layoutSubviews()\n        updateMask()\n    }\n\n    private func updateMask() {\n        let path = UIBezierPath()\n        path.move(to: CGPoint(x: bounds.minX + offset, y: bounds.minY))\n        path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))\n        path.addLine(to: CGPoint(x: bounds.maxX - offset, y: bounds.maxY))\n        path.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY))\n        path.close()\n\n        let shapeLayer = CAShapeLayer()\n        shapeLayer.path = path.cgPath\n        layer.mask = shapeLayer\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n