Ios 清除视图中的图层会使应用程序在下一次迭代中崩溃
我现在有一个非常简单的应用程序。我在用户手指移动的地方画线,当他们抬起手指时,我想清除图形,当他们再次绘制时,显示新的线 但是,当我第一次清除这些行时,下一次按下会导致崩溃,并且没有错误消息。我觉得我做错了一件小事,但我想不出来。这是我的密码: 我收到一条EXC错误访问消息Ios 清除视图中的图层会使应用程序在下一次迭代中崩溃,ios,objective-c,swift,uipangesturerecognizer,Ios,Objective C,Swift,Uipangesturerecognizer,我现在有一个非常简单的应用程序。我在用户手指移动的地方画线,当他们抬起手指时,我想清除图形,当他们再次绘制时,显示新的线 但是,当我第一次清除这些行时,下一次按下会导致崩溃,并且没有错误消息。我觉得我做错了一件小事,但我想不出来。这是我的密码: 我收到一条EXC错误访问消息 var prevX: CGFloat! var prevY: CGFloat! var startX: CGFloat = 150 var startY : CGFloat = 450 var reset: Bool
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 code=1,address=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()
}
因为如果我删除它,它可以正常工作,只是没有清除前一行问题是已经有子层可供查看,您正在删除这些子层以及您添加的子层。您只想删除添加的子图层。我添加了一个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
}
}
这里有一种方法,它需要更少的代码,并且只使用一个层。您不需要删除该层,只需删除其路径即可
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
}
}
}
请指出你从哪里得到的异常。我甚至不太确定。它不会进入pan回调。我在开头放了一个print语句,但它没有出现。我用堆栈跟踪更新了这个问题。这看起来是一个非常糟糕的作图方法。为什么每次移动手指时都要添加一个新的贝塞尔路径和层?@rdelmar我想画一条线来显示用户移动手指的位置,有什么更好的方法来实现这一点?哦,这太棒了!非常感谢@rdelmar