从视图中清除图层会在下次迭代时使应用程序崩溃



我现在有一个非常简单的应用程序。我在用户手指去的地方画线,当他们抬起手指时,我想清除绘图,当他们再次绘制时显示新线条。

但是,当我第一次清除行时,下一次按下会导致崩溃,没有错误消息。我想我做错了什么小事,但无法弄清楚。这是我的代码:

我收到EXC__BAD_ACCESS消息

 var prevX: CGFloat!
var prevY: CGFloat!
var startX: CGFloat = 150
var startY : CGFloat = 450
var reset: Bool = true
override func viewDidLoad() {
    super.viewDidLoad()
    var pan = UIPanGestureRecognizer(target: self, action: "pan:")
    pan.cancelsTouchesInView = false
    pan.delegate = self
    self.view.addGestureRecognizer(pan)
}
func pan(recognizer:UIPanGestureRecognizer) {
    print(self.view.layer)
    var state = recognizer.state
    if (state == UIGestureRecognizerState.Ended) {
        reset = true
        var sublayers = self.view.layer.sublayers
        for layer in sublayers {
            layer.removeFromSuperlayer()
        }
    } else {
        var interval = recognizer.translationInView(self.view)
        if (reset) {
            reset = false
            prevX = CGFloat(startX + interval.x)
            prevY = CGFloat(startY + interval.y)
        }
        var newPointX = startX + interval.x
        var newPointY = startY + interval.y
        var path = UIBezierPath().bezierPathByReversingPath()
        path.moveToPoint(CGPoint(x: prevX, y: prevY))
        path.addLineToPoint(CGPoint(x:newPointX, y:newPointY))
        var shapeLayer = CAShapeLayer()
        shapeLayer.path = path.CGPath
        shapeLayer.strokeColor = UIColor.blueColor().CGColor
        shapeLayer.lineWidth = 1.0
        shapeLayer.fillColor = UIColor.clearColor().CGColor
        self.view.layer.addSublayer(shapeLayer)
        prevX = newPointX
        prevY = newPointY
    }
}

我不太确定堆栈跟踪出现在哪里。我在 pan 回调的顶部放了一个 print 语句,并且没有被调用,所以我认为它不会发生这种情况。它只是打开

import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?

给出消息线程 1:EXC_BAD_ACCESS代码=1,地址=0x499e....

再多一点,顶部消息中显示错误消息:

___UIApplicationExtensionGetAccurateShareServicesExtensionForIdentifier_block_invoke_2
0x18c00e3c0:  adrp   x8, 54568
0x18c00e3c4:  ldr    x8, [x8, #2248]
0x18c00e3c8:  ldr    x8, [x8]
0x18c00e3cc:  ldr    x9, [sp, #56]
0x18c00e3d0:  sub    x8, x8, x9
0x18c00e3d4:  cbnz   x8, 0x18c00e3fc           ; UIApplicationMain + 1548
0x18c00e3d8:  movz   w0, #0

我知道这是这条线正在做的事情:

            for layer in sublayers {
            layer.removeFromSuperlayer()
        }

因为如果我删除它,它可以正常工作(只是不清除上一行)

问题是已经有用于view的子图层,并且您正在将其与添加的子图层一起删除。 您只想移除添加的子图层。 我添加了一个myLayers数组来保存新的子层,并使用它来删除添加的子层:

var prevX: CGFloat!
var prevY: CGFloat!
var startX: CGFloat = 150
var startY : CGFloat = 450
var reset: Bool = true
var myLayers: [CAShapeLayer] = []
override func viewDidLoad() {
    super.viewDidLoad()
    var pan = UIPanGestureRecognizer(target: self, action: "pan:")
    pan.cancelsTouchesInView = false
    pan.delegate = self
    self.view.addGestureRecognizer(pan)
}
func pan(recognizer:UIPanGestureRecognizer) {
    print(self.view.layer)
    var state = recognizer.state
    if (state == UIGestureRecognizerState.Ended) {
        reset = true
        for layer in myLayers {
            layer.removeFromSuperlayer()
        }
        myLayers = []
    } else {
        var interval = recognizer.translationInView(self.view)
        if (reset) {
            reset = false
            prevX = CGFloat(startX + interval.x)
            prevY = CGFloat(startY + interval.y)
        }
        var newPointX = startX + interval.x
        var newPointY = startY + interval.y
        var path = UIBezierPath().bezierPathByReversingPath()
        path.moveToPoint(CGPoint(x: prevX, y: prevY))
        path.addLineToPoint(CGPoint(x:newPointX, y:newPointY))
        var shapeLayer = CAShapeLayer()
        shapeLayer.path = path.CGPath
        shapeLayer.strokeColor = UIColor.blueColor().CGColor
        shapeLayer.lineWidth = 1.0
        shapeLayer.fillColor = UIColor.clearColor().CGColor
        self.view.layer.addSublayer(shapeLayer)
        myLayers.append(shapeLayer)
        prevX = newPointX
        prevY = newPointY
    }
}
<</div> div class="one_answers">

这是一种需要更少代码并且只使用一层的方法。您不需要删除该图层,只需删除其路径即可。

class ViewController: UIViewController, UIGestureRecognizerDelegate {
    var path: UIBezierPath!
    var shapeLayer = CAShapeLayer()
    override func viewDidLoad() {
        super.viewDidLoad()
        let pan = UIPanGestureRecognizer(target: self, action: "pan:")
        view.addGestureRecognizer(pan)
        shapeLayer.strokeColor = UIColor.blueColor().CGColor
        shapeLayer.lineWidth = 1.0
        shapeLayer.fillColor = UIColor.clearColor().CGColor
        view.layer.addSublayer(shapeLayer)
    }

    func pan(recognizer:UIPanGestureRecognizer) {
        if recognizer.state == .Began {
            let loc = recognizer.locationInView(view)
            path = UIBezierPath()
            path.moveToPoint(loc)
        }else if recognizer.state == .Changed {
            var loc = recognizer.locationInView(view)
            path.addLineToPoint(loc)
            shapeLayer.path = path.CGPath
        }else if recognizer.state == .Ended {
            shapeLayer.path = nil
        }
    }
}

最新更新