I am creating custom parallelogram view and view is rendering fine with default offset value. But when i change the offset value from ib it's not working
@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
}
}
I changed the offset value from IB but it doesn't changes IB and simulator
A couple of thoughts:
As Daniel said, you really want to call
drawParallelgramin youroffsetobserver.Also, in
layoutSubviews, you’re updating theframeof your shape layer. You want to reset itspathand update your mask again.You’re just adding more and more strokes to your
UIBezierPath. You probably just want to make it a local variable and avoid adding more and more strokes to the existing path.The
prepareForInterfaceBuildersuggests some misconception about the purpose of this method. This isn’t for doing initialization when launching from IB. This is for doing some special configuration, above and beyond what is already done by theinitmethods, required by IB.E.g. If you have a sophisticated chart view where you’ll be programmatically providing real chart data programmatically later, but you wanted to see something in IB, nonetheless, you might have
prepareForInterfaceBuilderpopulate some dummy data, for example. But you shouldn’t repeat the configuration you already did ininitmethods.It’s not relevant here (because I’m going to suggest getting rid of these
initmethods), but for what it’s worth, if I need to do configuration duringinit, I generally write twoinitmethods:Note that in
init(frame:)I also supply a default value of.zero. That ensures that I’m covered in all three scenarios:CustomView()CustomView(frame:); orCustomView(decoder:).In short, I get three
initmethods for the price of two. Lol.All that being said, you can greatly simplify this: