CALayerInvalidGeometry:CALayer位置在尝试调整具有可变大小和纵横比的小型远程svg的大小时包含NaN

CALayerInvalidGeometry:CALayer位置在尝试调整具有可变大小和纵横比的小型远程svg的大小时包含NaN,svg,swift3,uiwebview,calayer,Svg,Swift3,Uiwebview,Calayer,我想要达到的目标: 使用自动布局在我的应用程序中显示小的、可变大小的SVG。 SVG包含预渲染的乳胶公式。SVG是异步加载的,所以我不知道它们的大小或纵横比 我能想象的最艰难的先决条件 我尝试了几个svg显示库,结果没有人使用我们的svg,所以我决定使用UIWebView。 这里的问题是,SVG不应该是可滚动的,UIWebView的大小应该是最小的。 SVG应跨越所有可用宽度,并具有基于纵横比的高度 我尝试的是: class FormulaView: UIView, UIWebViewDeleg

我想要达到的目标: 使用自动布局在我的应用程序中显示小的、可变大小的SVG。 SVG包含预渲染的乳胶公式。SVG是异步加载的,所以我不知道它们的大小或纵横比

我能想象的最艰难的先决条件

我尝试了几个svg显示库,结果没有人使用我们的svg,所以我决定使用UIWebView。 这里的问题是,SVG不应该是可滚动的,UIWebView的大小应该是最小的。 SVG应跨越所有可用宽度,并具有基于纵横比的高度

我尝试的是:

class FormulaView: UIView, UIWebViewDelegate, XMLParserDelegate {

private var view: UIView!
@IBOutlet weak var webView: UIWebView!
@IBOutlet weak var topMargin: NSLayoutConstraint!
@IBOutlet weak var bottomMargin: NSLayoutConstraint!

private var width = -1.0
private var height = -1.0

// MARK: Initialisation
override init(frame: CGRect) {
    super.init(frame: frame)
    setUpView()
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
    setUpView()
}

// MARK: Set Up
// Performs the initial setup.
// Loads a XIB file into a view and returns this view.

func loadSVG(fromURL url: URL) {
    let request = NSURLRequest(url: url)
    webView.delegate = self
    webView.loadRequest(request as URLRequest)
}

func loadSVG(fromString string: String) {
    let url = URL(string: string)
    if url == nil {
        self.isHidden = true
        return
    }
    self.loadSVG(fromURL: url!)
}
var tableView: UITableView?

private func viewFromNibForClass() -> UIView {

    let bundle = Bundle(for: type(of: self))
    let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
    let view = nib.instantiate(withOwner: self, options: nil).first as! UIView

    return view
}

private func setUpView() {
    view = viewFromNibForClass()
    view.frame = bounds

    // Auto-layout stuff.
    view.autoresizingMask = [
        UIViewAutoresizing.flexibleWidth,
        UIViewAutoresizing.flexibleHeight
    ]
    addSubview(view)
    // Formula should take no space if no formula is loaded
    topMargin.constant = 0
    bottomMargin.constant = 0

    self.translatesAutoresizingMaskIntoConstraints = false
    self.addConstraints([
        NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal,
                toItem: view, attribute: .top, multiplier: 1.0, constant: 0),
        NSLayoutConstraint(item: self, attribute: .right, relatedBy: .equal,
                toItem: view, attribute: .right, multiplier: 1.0, constant: 0),
        NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal,
                toItem: view, attribute: .bottom, multiplier: 1.0, constant: 0),
        NSLayoutConstraint(item: self, attribute: .left, relatedBy: .equal,
                toItem: view, attribute: .left, multiplier: 1.0, constant: 0)
    ])
}

// MARK: - UIWebView delegate
func webViewDidFinishLoad(_ webView: UIWebView) {
    // Get xml of svg file
    let xml = webView.stringByEvaluatingJavaScript(from: "document.documentElement.outerHTML")
    let parser = XMLParser(data: (xml?.data(using: .utf8))!)
    parser.delegate = self
    parser.parse()
}

// MARK: - XMLParser delegate
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
    // Get width and height of svg
    if elementName == "svg" {
        self.height = Double(attributeDict["height"]?
            .replacingOccurrences(of: "pt", with: "") ?? "")
            ?? -1.0
        self.width = Double(attributeDict["width"]?
            .replacingOccurrences(of: "pt", with: "") ?? "")
            ?? -1.0
        let aspectRatio = self.width / self.height

        tableView?.beginUpdates()
        // Calculate height the webview should have based on the width and the normal aspect ratio of the svg
        let webviewHeight = self.webView.bounds.size.width / CGFloat(aspectRatio)

        if let constraint = (webView.constraints.filter {
            $0.firstAttribute == .height && $0.secondAttribute == .notAnAttribute
            }.first) {
            constraint.constant = webviewHeight
        } else {
            webView.heightAnchor.constraint(equalToConstant: webviewHeight).isActive = true
        }
        // Apply a 24 margin as a svg is now loaded
        topMargin.constant = 24
        bottomMargin.constant = 24
        tableView?.endUpdates()

        self.layoutIfNeeded()
        self.invalidateIntrinsicContentSize()
        // Zoom webview appropriately that the svg is completely visible and no scrolling is neccessary or even possible
        let scrollView = webView.scrollView
        let zoom = webView.bounds.size.width / scrollView.contentSize.width
        scrollView.maximumZoomScale = zoom
        scrollView.setZoomScale(zoom, animated: true) // Error occurs here
        // prevent scrolling
        scrollView.isScrollEnabled = false
        scrollView.isPagingEnabled = false
        scrollView.isUserInteractionEnabled = false
        scrollView.isDirectionalLockEnabled = true
    }
}
}
当我在模拟器上测试时,这个版本似乎运行良好, 但在某些情况下((编辑:我只在我们的Bug报告工具中看到这些崩溃),我在这行
scrollView.setZoomScale(缩放,动画:true)
上得到一个错误(
CALayerInvalidGeometry:CALayer position包含NaN:[NaN NaN NaN]

计算
zoom
似乎会产生
CGFloat.nan

(1) 但这是什么时候发生的,

(2) 我怎样才能防止这种情况发生

(3) 如果出现这种情况,如何计算这些情况下的缩放

编辑:或者换句话说,为什么
webView.bounds.size.width
和/或
scrollView.contentSize.width
是非正值

如果我能复制它,我可以说更多,但不幸的是我不能

提前感谢,,
Dennis

虽然我不知道Swift,但从阅读代码来看,我觉得奇怪的是,在
func parser
中,您似乎为SVG宽度/高度定义了一个默认值
-1.0
。此外,您是否可以排除SVG大小包含其他单位,如
%
px
?是的,我可以排除
pt
以外的其他单位。我已经重写了我的代码,因此没有可选单位,但无法解决问题。虽然我不知道Swift,仅从阅读代码来看,我觉得奇怪的是,在
func parser
中,您似乎为SVG宽度/高度定义了一个默认值
-1.0
。此外,您是否可以排除SVG大小包含其他单位,如
%
px
?是的,我可以排除
pt
以外的其他单位。我已经重写了代码,因此没有可选单位,但没有解决问题。