ios - CAShapeLayer 在 XIB swift iOS 中不可见

标签 ios swift interface-builder xib cashapelayer

我正在使用 XIB 文件构建自定义 View 。但是,我面临一个问题,即我添加到 View (trackLayer)的图层未显示在 xib 上(circleLayer 是一个动画,我不希望它在 xib 中渲染,据我所知这是不可能的)。 XIB的所有者类的代码如下所示:

@IBDesignable
class SpinningView: UIView {

@IBOutlet var contentView: SpinningView!

//MARK: Properties
let circleLayer = CAShapeLayer()
let trackLayer = CAShapeLayer()

let circularAnimation: CABasicAnimation = {
    let animation = CABasicAnimation()
    animation.fromValue = 0
    animation.toValue = 1
    animation.duration = 2
    animation.fillMode = kCAFillModeForwards
    animation.isRemovedOnCompletion = false
    return animation
}()

//MARK: IB Inspectables
@IBInspectable var strokeColor: UIColor = UIColor.red {
    ...
}

@IBInspectable var trackColor: UIColor = UIColor.lightGray {
    ...
}

@IBInspectable var lineWidth: CGFloat = 5 {
    ...
}

@IBInspectable var fillColor: UIColor = UIColor.clear {
    ...
}

@IBInspectable var isAnimated: Bool = true {
    ...
}

//MARK: Initialization
override init(frame: CGRect) {
    super.init(frame: frame)
    initSubviews()
}

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

    setup()
    initSubviews()
}

//MARK: Private functions
private func setup() {
    setupTrack()
    setupAnimationOnTrack()
}

private func setupTrack(){
    trackLayer.lineWidth = lineWidth
    trackLayer.fillColor = fillColor.cgColor
    trackLayer.strokeColor = trackColor.cgColor
    layer.addSublayer(trackLayer)
}

private func setupAnimationOnTrack(){
    circleLayer.lineWidth = lineWidth
    circleLayer.fillColor = fillColor.cgColor
    circleLayer.strokeColor = strokeColor.cgColor
    circleLayer.lineCap = kCALineCapRound
    layer.addSublayer(circleLayer)
    updateAnimation()
}

private func updateAnimation() {
    if isAnimated {
        circleLayer.add(circularAnimation, forKey: "strokeEnd")
    }
    else {
        circleLayer.removeAnimation(forKey: "strokeEnd")
    }
}

//MARK: Layout contraints
override func layoutSubviews() {
    super.layoutSubviews()

    let center = CGPoint(x: bounds.midX, y: bounds.midY)
    let radius = min(bounds.width / 2, bounds.height / 2) - circleLayer.lineWidth / 2

    let startAngle = -CGFloat.pi / 2
    let endAngle = 3 * CGFloat.pi / 2
    let path = UIBezierPath(arcCenter: .zero, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)

    trackLayer.position = center
    trackLayer.path = path.cgPath

    circleLayer.position = center
    circleLayer.path = path.cgPath
}

private func initSubviews() {
    let bundle = Bundle(for: SpinningView.self)
    let nib = UINib(nibName: "SpinningView", bundle: bundle)
    nib.instantiate(withOwner: self, options: nil)
    contentView.frame = bounds
    addSubview(contentView)
}
}

当 View 在 Main.storyboard 中子类化时,我可以看到图像和轨迹层,如下所示 IB UIView但是当我转到 XIB 时,它没有 trackLayer(图像周围的圆圈)XIB Image 。虽然有人可能会说它正在工作以及为什么我要为此烦恼,但我认为正确设计 XIB 很重要,因为其他人可能只是将其视为只有图像的 View (不知道动画功能)

最佳答案

当您设计 XIB 时,它不是您的 @IBDesignable SpinningView实例。实际上,您正在查看 SpinningView

因此,其背后的代码此时并未运行 - 它仅在您将 SpinningView 实例添加到另一个 View 时运行。

看一下这个简单的例子:

@IBDesignable
class SpinningView: UIView {

    @IBOutlet var contentView: UIView!
    @IBOutlet var theLabel: UILabel!

    //MARK: Initialization
    override init(frame: CGRect) {
        super.init(frame: frame)
        initSubviews()
    }

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

    private func initSubviews() {
        let bundle = Bundle(for: SpinningView.self)
        let nib = UINib(nibName: "SpinningView", bundle: bundle)
        nib.instantiate(withOwner: self, options: nil)
        contentView.frame = bounds
        addSubview(contentView)

        // this will change the label's textColor in Storyboard
        // when a UIView's class is set to SpinningView
        theLabel.textColor = .red
    }

}

当我设计 XIB 时,我看到的是这样的:

enter image description here

但是当我将 UIView 添加到另一个 View ,并将其类指定为 SpinningView 时,这就是我看到的:

enter image description here

标签的文本颜色更改为红色,因为代码正在运行。

另一种思考方式...您将 trackColorfillColor 等变量定义为 @IBInspectable。当您设计 XIB 时,您不会在 Xcode 的 Attributes Inspector 面板中看到这些属性 - 只有当您选择了已在其他位置添加的 SpinningView 实例时,您才会看到它们。

希望这是有道理的。

关于ios - CAShapeLayer 在 XIB swift iOS 中不可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49068774/

相关文章:

ios - 当变量值改变时如何改变 View 的框架?

swift - 如何从 firebase 中删除帖子? swift

ios - 将自定义坐标设置为函数,Waze Integration

ios - Xcode - 如何修复 'NSUnknownKeyException' ,原因 : … this class is not key value coding-compliant for the key X"error?

iphone - UITextView 中不必要的换行符

ios - 正则表达式在使用 MVC 设计模式的 iOS 应用程序中的什么位置?

ios - 在 Swift for iOS 中使用 BWWWalkthroughController 的转换错误

ios - 选项卡栏的 Interface Builder 问题

ios - 在 Assets 目录中切片 PDF 资源是否损坏?

ios - 在 swift 中动态加载类的实例