手势更新中的迅速崩溃

时间:2016-02-09 13:24:45

标签: ios swift pdf uipangesturerecognizer wkwebview

我正在使用约束来设置两个视图之间的边界。平移手势用于跟踪用户手指在拖动边界时的垂直移动。

当拖动时间过长时,应用程序崩溃,几乎没有任何解释。下面是崩溃的输出(其他崩溃产生了更短的输出),我不明白。我认为相关的代码低于它。

非常感谢您帮助理解和纠正此问题。谢谢。

libobjc.A.dylib`objc_msgSend:
    0x180d95bc0 <+0>:   cmp    x0, #0
    0x180d95bc4 <+4>:   b.le   0x180d95c2c               ; <+108>
->  0x180d95bc8 <+8>:   ldr    x13, [x0]
    0x180d95bcc <+12>:  and    x9, x13, #0x1fffffff8
    0x180d95bd0 <+16>:  ldp    x10, x11, [x9, #16]
    0x180d95bd4 <+20>:  and    w12, w1, w11
    0x180d95bd8 <+24>:  add    x12, x10, x12, lsl #4
    0x180d95bdc <+28>:  ldp    x16, x17, [x12]
    0x180d95be0 <+32>:  cmp    x16, x1
    0x180d95be4 <+36>:  b.ne   0x180d95bec               ; <+44>
    0x180d95be8 <+40>:  br     x17
    0x180d95bec <+44>:  cbz    x16, 0x180d95d80          ; _objc_msgSend_uncached_impcache
    0x180d95bf0 <+48>:  cmp    x12, x10
    0x180d95bf4 <+52>:  b.eq   0x180d95c00               ; <+64>
    0x180d95bf8 <+56>:  ldp    x16, x17, [x12, #-16]!
    0x180d95bfc <+60>:  b      0x180d95be0               ; <+32>
    0x180d95c00 <+64>:  add    x12, x12, w11, uxtw #4
    0x180d95c04 <+68>:  ldp    x16, x17, [x12]
    0x180d95c08 <+72>:  cmp    x16, x1
    0x180d95c0c <+76>:  b.ne   0x180d95c14               ; <+84>
    0x180d95c10 <+80>:  br     x17
    0x180d95c14 <+84>:  cbz    x16, 0x180d95d80          ; _objc_msgSend_uncached_impcache
    0x180d95c18 <+88>:  cmp    x12, x10
    0x180d95c1c <+92>:  b.eq   0x180d95c28               ; <+104>
    0x180d95c20 <+96>:  ldp    x16, x17, [x12, #-16]!
    0x180d95c24 <+100>: b      0x180d95c08               ; <+72>
    0x180d95c28 <+104>: b      0x180d95d80               ; _objc_msgSend_uncached_impcache
    0x180d95c2c <+108>: b.eq   0x180d95c44               ; <+132>
    0x180d95c30 <+112>: adrp   x10, 123003
    0x180d95c34 <+116>: add    x10, x10, #816
    0x180d95c38 <+120>: lsr    x11, x0, #60
    0x180d95c3c <+124>: ldr    x9, [x10, x11, lsl #3]
    0x180d95c40 <+128>: b      0x180d95bd0               ; <+16>
    0x180d95c44 <+132>: movz   x1, #0
    0x180d95c48 <+136>: movi   d0, #0000000000000000
    0x180d95c4c <+140>: movi   d1, #0000000000000000
    0x180d95c50 <+144>: movi   d2, #0000000000000000
    0x180d95c54 <+148>: movi   d3, #0000000000000000
    0x180d95c58 <+152>: ret    
    0x180d95c5c <+156>: nop    

以下是平移手势识别器调用的代码:

@IBAction func pan(gesture: UIPanGestureRecognizer) {
    switch gesture.state {
    case .Ended:
        captureViewSplit()
        saveSermonSettingsBackground()
        break

    case .Changed:
        let translation = gesture.translationInView(splitView)
        let change = -translation.y
        if change != 0 {
            gesture.setTranslation(CGPointZero, inView: splitView)
            setSermonNotesAndSlidesConstraint(change)
            self.view.setNeedsLayout()
            self.view.layoutSubviews()
        }
        break

    default:
        break
    }
}

以下是约束更新的代码:

private func setSermonNotesAndSlidesConstraint(change:CGFloat)
{
    let newConstraintConstant = self.sermonNotesAndSlidesConstraint.constant + change

    let (minConstraintConstant,maxConstraintConstant) = sermonNotesAndSlidesConstraintMinMax(self.view.bounds.height)

    if (newConstraintConstant >= minConstraintConstant) && (newConstraintConstant <= maxConstraintConstant) {
        self.sermonNotesAndSlidesConstraint.constant = newConstraintConstant
    } else {
        if newConstraintConstant < minConstraintConstant { self.sermonNotesAndSlidesConstraint.constant = minConstraintConstant }
        if newConstraintConstant > maxConstraintConstant { self.sermonNotesAndSlidesConstraint.constant = maxConstraintConstant }
    }
    splitView.min = minConstraintConstant
    splitView.max = maxConstraintConstant
    splitView.height = self.sermonNotesAndSlidesConstraint.constant
    self.view.setNeedsLayout()
}

private func sermonNotesAndSlidesConstraintMinMax(height:CGFloat) -> (min:CGFloat,max:CGFloat)
{
    let minConstraintConstant:CGFloat = tableView.rowHeight*1 + slider.bounds.height + 16 //margin on top and bottom of slider

    let maxConstraintConstant:CGFloat = height - logo.bounds.height - slider.bounds.height - navigationController!.navigationBar.bounds.height

    return (minConstraintConstant,maxConstraintConstant)
}

下面是绘制描绘两个视图之间分割的图形的自定义类的代码。

@IBDesignable
class SplitView: UIView {
    var splitViewController:UISplitViewController?

    var lineWidth: CGFloat = 1.0 { didSet { setNeedsDisplay() } }

    var color: UIColor = UIColor.blackColor() { didSet { setNeedsDisplay() } }

    var scale: CGFloat = 1.0 { didSet { setNeedsDisplay() } }

    var height:CGFloat = 200 {
        didSet {
            setNeedsDisplay()
        }
    }

    var min:CGFloat = 50 {
        didSet {
            setNeedsDisplay()
        }
    }

    var max:CGFloat = 500 {
        didSet {
            setNeedsDisplay()
        }
    }

    private var splitCenter: CGPoint? {
        var splitPoint:CGPoint?

        splitPoint = CGPointMake(self.bounds.width / 2, self.bounds.height - height)

        return splitPoint
    }

    override func drawRect(rect: CGRect)
    {
        if let startingPoint = splitCenter {
            let context = UIGraphicsGetCurrentContext()
            CGContextSaveGState(context)

            let indicatorPath = UIBezierPath()

            let height:CGFloat = bounds.width/4

            let left = CGPoint(x: startingPoint.x - bounds.width/2, y: startingPoint.y)
            indicatorPath.moveToPoint(left)

            let right = CGPoint(x: startingPoint.x + bounds.width/2, y: startingPoint.y)
            indicatorPath.addLineToPoint(right)

//            print("startingPoint.y: \(round(startingPoint.y)) min: \(round(min)) max: \(round(max))")

            if (round(startingPoint.y) > (bounds.height - round(max))) {
                let bottom = CGPoint(x: startingPoint.x, y: startingPoint.y - height)
                indicatorPath.moveToPoint(bottom)
                indicatorPath.addLineToPoint(left)
                indicatorPath.moveToPoint(bottom)
                indicatorPath.addLineToPoint(right)
            }

            if (round(startingPoint.y) < (bounds.height - round(min))) {
                let top = CGPoint(x: startingPoint.x, y: startingPoint.y + height)
                indicatorPath.moveToPoint(top)
                indicatorPath.addLineToPoint(left)
                indicatorPath.moveToPoint(top)
                indicatorPath.addLineToPoint(right)
            }

            indicatorPath.lineWidth = lineWidth
            color.set()
            indicatorPath.stroke()

            let boundsPath = UIBezierPath()

            boundsPath.moveToPoint(bounds.origin)
            boundsPath.addLineToPoint(CGPoint(x: bounds.origin.x + bounds.width, y: bounds.origin.y))

            if (splitViewController == nil) {
                boundsPath.addLineToPoint(CGPoint(x: bounds.origin.x + bounds.width,    y: splitCenter!.y))
                boundsPath.addLineToPoint(CGPoint(x: bounds.origin.x,                   y: splitCenter!.y))
            } else {
                boundsPath.addLineToPoint(CGPoint(x: bounds.origin.x + bounds.width,    y: bounds.origin.y + bounds.height))
                boundsPath.addLineToPoint(CGPoint(x: bounds.origin.x,                   y: bounds.origin.y + bounds.height))
            }

            boundsPath.addLineToPoint(bounds.origin)

            boundsPath.lineWidth = lineWidth / 2
            color.set()
            boundsPath.stroke()

            CGContextRestoreGState(context)
        } else {
            print("No starting point!")
        }
    }
}

1 个答案:

答案 0 :(得分:0)

问题是我正在设置WKWebView的scrollView委托,根据经验,我发现必须在viewWillDisappear()上设置为nil,否则应用程序会崩溃。通过将代理设置为nil on .Began在平移手势识别器中并返回自我.Ended问题消失了。