调用removeFromSuperview()后greenView上的线条未删除,该如何解决?
问题:移除并重新添加UIView后,其上的CAShapeLayer线条仍存在,如何删除?
我创建了一个greenView:
static func createRectView( x: Float, y: Float, width: Float, height: Float, color: UIColor, transparency: Float ) -> UIView { let viewRectFrame = CGRect( x: CGFloat(x), y: CGFloat(y), width: CGFloat(width), height: CGFloat(height) ) let retView = UIView(frame:viewRectFrame) retView.backgroundColor = color retView.alpha = CGFloat(transparency) return retView } let greenView: UIView = createRectView( x: 50, y: 110, width: 150, height: 100, color: .green, transparency: 1 ) view.addSubview(greenView)
接着在greenView上绘制了一条线条:
func getPath() -> UIBezierPath { let path = UIBezierPath() path.move(to: CGPoint(x: 0, y: 0)) path.addLine(to: pointDef5) return path } func createLine(on view: UIView) { let shapeLayer = CAShapeLayer() view.layer.addSublayer(shapeLayer) shapeLayer.strokeColor = UIColor.black.cgColor shapeLayer.lineWidth = 5 shapeLayer.fillColor = nil shapeLayer.path = getPath().cgPath } createLine(on: greenView)
之后执行了移除并重新添加greenView的操作:
greenView.removeFromSuperview() view.addSubview(greenView)
但greenView上的旧线条依然存在,请问该如何删除这条线条?难道greenView和线条绑定后就无法删除了吗?
解决方案
核心原因
线条是作为CAShapeLayer添加到greenView的layer层级中的,移除greenView再重新添加时,仅会改变它在父视图中的层级位置,其内部的layer子层结构不会自动清空——greenView与它的layer是绑定关系,视图本身的移除不会影响内部layer的存在。
方法1:保存ShapeLayer引用,直接移除
这是最精准的方式,创建线条时保留CAShapeLayer的引用,需要删除时直接调用移除方法:
// 在类中定义属性保存线条的layer引用 var lineLayer: CAShapeLayer? func createLine(on view: UIView) { let shapeLayer = CAShapeLayer() view.layer.addSublayer(shapeLayer) shapeLayer.strokeColor = UIColor.black.cgColor shapeLayer.lineWidth = 5 shapeLayer.fillColor = nil shapeLayer.path = getPath().cgPath // 保存引用以便后续操作 lineLayer = shapeLayer } // 需要删除线条时执行 lineLayer?.removeFromSuperlayer() lineLayer = nil // 清空引用避免内存泄漏
方法2:通过标识查找并删除Layer
如果没有保存引用,可以给CAShapeLayer设置唯一名称,后续遍历子层查找并删除:
func createLine(on view: UIView) { let shapeLayer = CAShapeLayer() shapeLayer.name = "customGreenViewLine" // 添加唯一标识 view.layer.addSublayer(shapeLayer) shapeLayer.strokeColor = UIColor.black.cgColor shapeLayer.lineWidth = 5 shapeLayer.fillColor = nil shapeLayer.path = getPath().cgPath } // 删除线条时遍历子层 greenView.layer.sublayers?.forEach { layer in // 匹配类型和名称,精准删除目标线条 if layer is CAShapeLayer && layer.name == "customGreenViewLine" { layer.removeFromSuperlayer() } }
方法3:清空所有子层(谨慎使用)
如果greenView的layer上仅存在这一个自定义子层,可以直接清空所有子层:
// 方式1:遍历移除每个子层 greenView.layer.sublayers?.forEach { $0.removeFromSuperlayer() } // 方式2:直接赋值为空数组 greenView.layer.sublayers = nil
注意:此方法会删除greenView.layer上所有自定义子层,若有其他需要保留的layer(比如阴影层、圆角层),请勿使用。
优化建议:重新添加视图前清除线条
若你需要在移除greenView后重新添加时不带旧线条,可在移除视图前先执行线条删除操作:
// 先删除线条 lineLayer?.removeFromSuperlayer() // 再移除视图 greenView.removeFromSuperview() // 最后重新添加 view.addSubview(greenView)
内容的提问来源于stack exchange,提问作者Swift Lilu
相关产品推荐
相关产品推荐

