调用 setNeedsDisplay 时的 Swift 奇怪行为
Posted
技术标签:
【中文标题】调用 setNeedsDisplay 时的 Swift 奇怪行为【英文标题】:Swift weird behavior when setNeedsDisplay is called 【发布时间】:2015-04-29 18:32:00 【问题描述】:我正在制作一个模拟发动机油门的应用。当我滑动 UISlider 时,我希望 RPM 量规指针增加并且 RPM 量规内的 UILabel 更新。除了一个奇怪的部分外,我一切正常: UILabel 中的文本会覆盖自身(即,它会将自身绘制在自身之上,以便所有值相互叠加并且不可读)。这是我的 ViewController 中的滑块代码:
@IBAction func changeThrottleSetting(sender: UISlider)
compactEngineView.RPMPointerAngleInt = Int(sender.value)
compactEngineView.setNeedsDisplay()
然后在 compactEngineView 本身中:
var RPMPointerAngleInt = Int()
var RPMPointerAngle: CGFloat //this angle is used to draw the pointer points later down in the code, didn't show it here just to keep it shorter
var AngleCGFloat = CGFloat(RPMPointerAngleInt)
var Pi = CGFloat(M_PI)
var CorrectedAngle = (9 * Pi / 800) * AngleCGFloat - (Pi/2) //just some math to make it look right on the display
return CorrectedAngle
var RPMPercentageValue: Int
var correctedValue = (0.55) * Float(RPMPointerAngleInt) + 55
return Int(correctedValue)
override func drawRect(rect: CGRect)
let RPMPointerPath = UIBezierPath()
RPMPointerPath.moveToPoint(RPMPointer1)
RPMPointerPath.addLineToPoint(RPMPointer2)
RPMPointerPath.addLineToPoint(RPMPointer3)
RPMPointerPath.addLineToPoint(RPMPointer1)
whiteColor.set()
RPMPointerPath.stroke()
RPMPointerPath.fill()
//here is the troublemaker
let RPMdisplaylabel = UILabel(frame: CGRectMake(0, 0, 81, 32))
RPMdisplaylabel.center = RPMdisplayLocation
RPMdisplaylabel.textAlignment = NSTextAlignment.Right
RPMdisplaylabel.text = "\(RPMPercentageValue)%"
RPMdisplaylabel.textColor = UIColor.whiteColor()
RPMdisplaylabel.font = UIFont(name: "HelveticaNeue",
size: 27.0)
self.addSubview(RPMdisplaylabel)
指针完美运行。没什么好抱怨的。但是每次我移动滑块时,文本都会自动覆盖。 DrawRect 部分中的 UILabels 有单独的技巧吗?谢谢!
【问题讨论】:
【参考方案1】://here is the troublemaker
let RPMdisplaylabel = UILabel(frame: CGRectMake(0, 0, 81, 32))
RPMdisplaylabel.center = RPMdisplayLocation
RPMdisplaylabel.textAlignment = NSTextAlignment.Right
RPMdisplaylabel.text = "\(RPMPercentageValue)%"
RPMdisplaylabel.textColor = UIColor.whiteColor()
RPMdisplaylabel.font = UIFont(name: "HelveticaNeue",
size: 27.0)
self.addSubview(RPMdisplaylabel)
你正在做一些你不应该做的事情:在drawRect:
,你所做的不仅仅是在矩形内绘图! drawRect:
的工作是在矩形内绘制内容,不多也不少。 不是添加子视图的地方!您已经发现了其中一个原因:由于在应用程序的生命周期中可以调用数千次 drawRect:
,因此您最终会添加数千个相同的子视图。
所以这里发生的事情是,你正在创建和添加一个 UILabel,一次又一次,一次又一次......所以你最终得到了无数的 UILabel,所有这些都在同一个位置,因此相互重叠并给出结果你说得对。
解决方案:在其他地方添加一次标签。不要为此滥用drawRect:
。
【讨论】:
谢谢@matt。我尝试将它移到 UIView 代码中的DrawRect
之外,但是当我这样做时,我第一次尝试说 RPMdisplaylabel.center
时出现错误:“预期声明。”
我也尝试将整个内容移动到 ViewController,但我遇到的问题与原来的问题相同,即文本覆盖自身。
您能提供关于将其移动到哪里/如何移动它的建议吗?
我做了更多的移动,并找到了放置所有东西的正确位置。再次感谢。以上是关于调用 setNeedsDisplay 时的 Swift 奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章
如果我经常调用 setneedsdisplay,drawrect 多久会被调用一次?这是为啥?
setNeedsDisplay() 没有调用 draw(_ rect: CGRect)