CALayerInvalidGeometry:CALayer位置在尝试调整具有可变大小和纵横比的小型远程svg的大小时包含NaN
我想要达到的目标: 使用自动布局在我的应用程序中显示小的、可变大小的SVG。 SVG包含预渲染的乳胶公式。SVG是异步加载的,所以我不知道它们的大小或纵横比 我能想象的最艰难的先决条件 我尝试了几个svg显示库,结果没有人使用我们的svg,所以我决定使用UIWebView。 这里的问题是,SVG不应该是可滚动的,UIWebView的大小应该是最小的。 SVG应跨越所有可用宽度,并具有基于纵横比的高度 我尝试的是: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
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
以外的其他单位。我已经重写了代码,因此没有可选单位,但没有解决问题。