问题描述
背景
为了使文本视图水平滚动,我创建了一个自定义的UIView
子类.该类将一个UITextView
放入一个UIView
中,旋转并翻转该视图,然后将该视图放入父UIView
中.
In order to make a text view that scrolls horizontally for vertical Mongolian script, I made a custom UIView
subclass. The class takes a UITextView
, puts it in a UIView
, rotates and flips that view, and then puts that view in a parent UIView
.
旋转和翻转的目的是使文本垂直,并使换行正确.将所有内容粘贴在父UIView
中的目的是使自动"布局可以在情节提要中使用. (请参见此处.)
The purpose for the rotation and flipping is so that the text will be vertical and so that line wrapping will work right. The purpose of sticking everything in a parent UIView
is so that Auto layout will work in a storyboard. (See more details here.)
代码
我有一个可行的解决方案. github上的完整代码是此处 >,但是我创建了一个新项目,并剥离了所有我可以解决的不必要代码.以下代码仍然执行上述基本功能,但仍然存在以下所述的缓慢加载问题.
I got a working solution. The full code on github is here, but I created a new project and stripped out all the unnecessary code that I could in order to isolate the problem. The following code still performs the basic function described above but also still has the slow loading problem described below.
import UIKit
@IBDesignable class UIMongolTextView: UIView {
private var view = UITextView()
private var oldWidth: CGFloat = 0
private var oldHeight: CGFloat = 0
@IBInspectable var text: String {
get {
return view.text
}
set {
view.text = newValue
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect){
super.init(frame: frame)
}
override func sizeThatFits(size: CGSize) -> CGSize {
// swap the length and width coming in and going out
let fitSize = view.sizeThatFits(CGSize(width: size.height, height: size.width))
return CGSize(width: fitSize.height, height: fitSize.width)
}
override func layoutSubviews() {
super.layoutSubviews()
// layoutSubviews gets called multiple times, only need it once
if self.frame.height == oldHeight && self.frame.width == oldWidth {
return
} else {
oldWidth = self.frame.width
oldHeight = self.frame.height
}
// Remove the old rotation view
if self.subviews.count > 0 {
self.subviews[0].removeFromSuperview()
}
// setup rotationView container
let rotationView = UIView()
rotationView.frame = CGRect(origin: CGPointZero, size: CGSize(width: self.bounds.height, height: self.bounds.width))
rotationView.userInteractionEnabled = true
self.addSubview(rotationView)
// transform rotationView (so that it covers the same frame as self)
rotationView.transform = translateRotateFlip()
// add view
view.frame = rotationView.bounds
rotationView.addSubview(view)
}
func translateRotateFlip() -> CGAffineTransform {
var transform = CGAffineTransformIdentity
// translate to new center
transform = CGAffineTransformTranslate(transform, (self.bounds.width / 2)-(self.bounds.height / 2), (self.bounds.height / 2)-(self.bounds.width / 2))
// rotate counterclockwise around center
transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))
// flip vertically
transform = CGAffineTransformScale(transform, -1, 1)
return transform
}
}
问题
我注意到自定义视图的加载速度非常慢.我是Xcode的新手,所以我观看了有用的视频使用Xcode和Profiler调试内存问题和时间分析器.
I noticed that the custom view loads very slowly. I'm new to Xcode Instruments so I watched the helpful videos Debugging Memory Issues with Xcode and Profiler and Time Profiler.
之后,我尝试在自己的项目中查找问题.似乎无论我使用时间分析器还是泄漏"或分配"工具,它们都表明我的类init
方法正在执行过多的工作. (但是我以前从缓慢的加载时间就已经知道了.)这是分配"工具的屏幕截图:
After that I tried finding the issue in my own project. It seems like no matter whether I use the Time Profiler or Leaks or Allocations tools, they all show that my class init
method is doing too much work. (But I kind of knew that already from the slow load time before.) Here is a screen shot from the Allocations tool:
我没有展开所有的调用树,因为它不合适.为什么要创建这么多对象?当我创建一个三层的自定义视图时,我知道它不是理想的,但是在调用树中似乎正在发生的层数太可笑了.我究竟做错了什么?
I didn't expand all of the call tree because it wouldn't have fit. Why are so many object being created? When I made a three layer custom view I knew that it wasn't ideal, but the number of layers that appears to be happening from the call tree is ridiculous. What am I doing wrong?
推荐答案
您不应在layoutSubviews
内部添加或删除任何子视图,因为这样做会再次触发对layoutSubviews
的调用.
You shouldn't add or delete any subview inside layoutSubviews
, as doing so triggers a call to layoutSubviews
again.
在创建视图时创建子视图,然后仅调整其在layoutSubviews
中的位置,而不是删除并重新添加它.
Create your subview when you create your view, and then only adjust its position in layoutSubviews
rather than deleting and re-adding it.
这篇关于Swift中自定义UIView的加载时间很慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!