为啥在 .addObserver 中以 NSException 类型的未捕获异常终止

Posted

技术标签:

【中文标题】为啥在 .addObserver 中以 NSException 类型的未捕获异常终止【英文标题】:Why terminating with uncaught exception of type NSException in .addObserver为什么在 .addObserver 中以 NSException 类型的未捕获异常终止 【发布时间】:2019-03-18 16:51:03 【问题描述】:

我将使用UIAttachmentBehavioranchorPoint 连接到特定的UIView,然后使用CAShapeLayer 画一条线。

我用addObserver 每分钟带上UIView 的坐标。

但是,发生未知错误。我想我不熟悉这个功能。

错误: libc++abi.dylib: terminating with uncaught exception of type NSException

代码:

//: A UIKit based Playground for presenting user interface

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController 
    private var animator: UIDynamicAnimator?
    private var gravity: UIGravityBehavior?
    private var attach: UIAttachmentBehavior?
    private var plateView: UIView?

    var lineLayer: CAShapeLayer?

    override func loadView() 
        let view = UIView()
        view.backgroundColor = .white
        self.view = view

        plateView = UIView(frame: CGRect(x: 80, y: 150, width: 60, height: 60))
        plateView?.backgroundColor = UIColor.orange
        self.view.addSubview(plateView!)

        animator = UIDynamicAnimator(referenceView: view)

        gravity = UIGravityBehavior(items: [plateView!])
        animator?.addBehavior(gravity!)

        attach = UIAttachmentBehavior(item: plateView!, offsetFromCenter: UIOffset(horizontal: 0, vertical: -30), attachedToAnchor: CGPoint(x: 200, y: 100))

        attach?.damping = 0.1
        attach?.frequency = 0.6
        animator?.addBehavior(attach!)

        plateView?.addObserver(self, forKeyPath: "center", options: .new, context: nil)

        func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) 
            updateLine()
        

        func updateLine() 
            if nil == lineLayer 
                lineLayer = CAShapeLayer()
                lineLayer?.strokeColor = UIColor.purple.cgColor
                lineLayer?.fillColor = UIColor.clear.cgColor
                lineLayer?.lineWidth = 1.5
                lineLayer?.lineJoin = .round
                lineLayer?.strokeEnd = 1.0
                self.view.layer.addSublayer(lineLayer!)
            

            let platePoint = view.convert(CGPoint(x: plateView!.bounds.midX, y: 0), from: plateView)
            let bezierPath = UIBezierPath()
            bezierPath.move(to: attach!.anchorPoint)
            bezierPath.addLine(to: platePoint)
            lineLayer?.path = bezierPath.cgPath
        
    

// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

我查了资料,但是问题太全面了,找不到明确的答案。

我需要了解和理解这个问题的原因。为什么我的代码会出现这个问题?

为了您的信息,我正在关注this 文档的教程。

【问题讨论】:

您的observeValue(...)updateLine() 方法需要在loadView 之外定义 @dan 即使没有方法,代码仍然有错误。在我看来,错误的问题是.addObserver 我把你的代码粘贴到了一个操场上,然后移动了这两个方法,效果很好 @dan 谢谢!你的知识:) 【参考方案1】:

您需要将observeValueForKeyPath:ofObject:change:contextupdateLine 函数移出loadView() 函数。

observeValueForKeyPath:ofObject:change:context 函数需要在 ViewController 级别覆盖,因为您在 self 上添加了观察者,在本例中是视图控制器。

见下文:

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController 
    private var animator: UIDynamicAnimator?
    private var gravity: UIGravityBehavior?
    private var attach: UIAttachmentBehavior?
    private var plateView: UIView?

    var lineLayer: CAShapeLayer?

    override func loadView() 
        let view = UIView()
        view.backgroundColor = .white
        self.view = view

        plateView = UIView(frame: CGRect(x: 80, y: 150, width: 60, height: 60))
        plateView?.backgroundColor = UIColor.orange
        self.view.addSubview(plateView!)

        animator = UIDynamicAnimator(referenceView: view)

        gravity = UIGravityBehavior(items: [plateView!])
        animator?.addBehavior(gravity!)

        attach = UIAttachmentBehavior(item: plateView!, offsetFromCenter: UIOffset(horizontal: 0, vertical: -30), attachedToAnchor: CGPoint(x: 200, y: 100))

        attach?.damping = 0.1
        attach?.frequency = 0.6
        animator?.addBehavior(attach!)

        plateView?.addObserver(self, forKeyPath: "center", options: .new, context: nil)
    

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) 
        updateLine()
    

    func updateLine() 
        if nil == lineLayer 
            lineLayer = CAShapeLayer()
            lineLayer?.strokeColor = UIColor.purple.cgColor
            lineLayer?.fillColor = UIColor.clear.cgColor
            lineLayer?.lineWidth = 1.5
            lineLayer?.lineJoin = .round
            lineLayer?.strokeEnd = 1.0
            self.view.layer.addSublayer(lineLayer!)
        

        let platePoint = view.convert(CGPoint(x: plateView!.bounds.midX, y: 0), from: plateView)
        let bezierPath = UIBezierPath()
        bezierPath.move(to: attach!.anchorPoint)
        bezierPath.addLine(to: platePoint)
        lineLayer?.path = bezierPath.cgPath
    


// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

【讨论】:

感谢您的知识! :)

以上是关于为啥在 .addObserver 中以 NSException 类型的未捕获异常终止的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能在 TypeScript 中以这种方式只读数组?

为啥你可以在 C 中以 $ 开头的变量名?

为啥我不能在 react native 中以编程方式添加道具?

为啥函数在 php 中以 @ 开头?像@unpack(xxx)? [复制]

为啥 lambda 参数在 C++11 中以只读方式传递?

为啥建议在 jmeter 中以非 gui 模式运行负载测试