创建 uiview 的渐变边框,崩溃更少

问题描述 投票:0回答:1

我有一段时间写了这个自定义代码,以便在我的视图上有一个渐变边框。唯一的问题是,它已经慢慢成为我的应用程序中最严重的崩溃问题。

我在 crashlytics 中收到的崩溃日志指向

super.layoutSubviews()
行,这对我来说没有多大意义。

有人对改进有任何想法,或者有不同的方法来做同样的事情,可以减少崩溃吗?我从这个视图中每周获得 120-200。

class GradientBorderView: UIView {
    var enableGradientBorder: Bool = false

    var borderGradientColors: [UIColor] = [] {
        didSet {
            setNeedsLayout()
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        guard enableGradientBorder && !borderGradientColors.isEmpty  else {
            layer.borderColor = nil
            return
        }
        let gradient = UIImage.imageGradient(bounds: bounds, colors: borderGradientColors)
        layer.borderColor = UIColor(patternImage: gradient).cgColor
    }
}


extension UIImage {

    static func imageGradient(bounds: CGRect, colors: [UIColor]) -> UIImage {
        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = bounds
        gradientLayer.colors = colors.map(\.cgColor)

        // This makes it left to right, default is top to bottom
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)

        let renderer = UIGraphicsImageRenderer(bounds: bounds)

        return renderer.image { gradientLayer.render(in: $0.cgContext) }
    }
}
ios swift cagradientlayer
1个回答
0
投票

很难说为什么你会崩溃,除非你可以提供重现它的代码。

但是,您可能会发现将

CAGradientLayer
.mask
结合使用是更好、更高效的选择:

class MyGradientBorderView: UIView {
    
    var enableGradientBorder: Bool = false { didSet { setNeedsLayout() } }
    
    var borderGradientColors: [UIColor] = [] { didSet { setNeedsLayout() } }
    
    var gradientBorderWidth: CGFloat = 8.0 { didSet { setNeedsLayout() } }
    
    let gLayer: CAGradientLayer = CAGradientLayer()
    let mskLayer: CAShapeLayer = CAShapeLayer()

    override func layoutSubviews() {
        super.layoutSubviews()

        guard enableGradientBorder, gradientBorderWidth > 0.0, !borderGradientColors.isEmpty  else {
            gLayer.removeFromSuperlayer()
            return
        }
        if gLayer.superlayer == nil {
            layer.addSublayer(gLayer)
        }

        gLayer.frame = bounds
        gLayer.colors = borderGradientColors.map(\.cgColor)
        gLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
        gLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
        
        let w: CGFloat = gradientBorderWidth
        
        mskLayer.path = UIBezierPath(rect: bounds.insetBy(dx: w * 0.5, dy: w * 0.5)).cgPath
        mskLayer.fillColor = UIColor.clear.cgColor
        mskLayer.strokeColor = UIColor.red.cgColor  // any opaque color
        mskLayer.lineWidth = w
        gLayer.mask = mskLayer
    }
    
}
© www.soinside.com 2019 - 2024. All rights reserved.