setNeedsDisplay() 没有调用 draw(_ rect: CGRect)
Posted
技术标签:
【中文标题】setNeedsDisplay() 没有调用 draw(_ rect: CGRect)【英文标题】:setNeedsDisplay() is not calling draw(_ rect: CGRect) 【发布时间】:2019-08-13 08:19:19 【问题描述】:我在这个网站上发现了类似的问题,但没有一个能解决我的问题。请仔细阅读整个代码。当我想在 MyView 上画一条线时,setNeedsDisplay()
函数没有调用 draw(_ rect: CGRect)
。
我在情节提要中创建了一个名为“myView”的视图作为“MyViewController”的子视图,并为视图控制器创建了一个IBOutlet
。
然后我创建了一个名为“MyViewClass”的类,并将其设置为情节提要中的“myView”类。
我将布尔值drawLine设置为true并调用函数updateLine()
,
问题是setNeedsDispaly()
没有触发draw(_ rect: CGRect)
函数。
import UIKit
class MyViewClass : UIView
var drawLine = Bool() // decides whether to draw the line
func updateLine()
setNeedsDisplay()
override func draw(_ rect: CGRect)
if drawLine == true
guard let context = UIGraphicsGetCurrentContext() else
return
context.setLineWidth(4.0)
context.setStrokeColor(UIColor.red.cgColor)
context.move(to: CGPoint(x: 415 , y: 650))
context.addLine(to: CGPoint(x:415 , y: 550))
context.strokePath()
class myViewController:UIViewController
@IBOutlet weak var insideView: UIView!
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view.
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
let myViewInstance = MyViewClass()
myViewInstance.drawLine = true
myViewInstance.updateLine()
我对 Swift 还很陌生。任何帮助将不胜感激。谢谢。
【问题讨论】:
请看看这个answer。我自己试过了,感觉如果视图不可见,它就不会调用drawRect。只需确认您计划更新的视图在将 drawLine 设置为 true 时可见。 视图永远不会添加到您的视图层次结构中,因此它永远不会被绘制。 你能告诉我如何将它添加到视图层次结构中,我只是将视图添加到主视图吗?因为我已经这样做了。 【参考方案1】:您有 2 个问题:
-
您没有为新视图提供
frame
,因此它默认为零宽度和零高度
您没有将视图添加到视图层次结构中
let myViewInstance = MyViewClass(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height))
myViewInstance.backgroundColor = .white // you might want this a well
myViewInstance.drawLine = true
self.view.addSubview(myViewInstance)
myViewInstance.updateLine()
当属性(例如drawLine
)发生更改时,让视图重绘的一种更简洁的方法是使用属性观察器:
var drawLine: Bool = true
didSet
setNeedsDisplay()
这样,当你改变一个属性时,视图会自动重绘,然后你就不需要updateLine()
了。
注意setNeedsDisplay
只是安排视图重绘。如果你在每个属性上都设置了这个,即使多个属性被改变,视图也只会重绘一次。
注意: viewDidLoad()
将是添加行的更合适的位置,因为它仅在创建 view
时调用一次。 viewWillAppear()
会在view
出现的任何时候被调用,因此它可以被多次调用(例如在UITabView
中,viewWillAppear()
会在用户每次切换到该选项卡时被调用)。
【讨论】:
感谢@vacawama,这解决了我的问题。非常感谢。【参考方案2】:MyView 类
class myView : UIView
var updateView : Bool = false
didSet
setNeedsDisplay()
override func draw(_ rect: CGRect)
print("in Draw")
我的视图控制器
class ViewController: UIViewController
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view.
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
let view = myView()
view.updateView = true
在故事板中,我将视图类设置为 myView,因此它是可见的。
希望这会对你有所帮助。
【讨论】:
感谢您的精心回复,我是否必须为此视图制作 IBOutlet?或者我可以将子视图添加到这个视图类的实例中吗? @JohnXavier 我还没有发表观点。 再次感谢@chirag90,您的回答也正确,不胜感激。以上是关于setNeedsDisplay() 没有调用 draw(_ rect: CGRect)的主要内容,如果未能解决你的问题,请参考以下文章
使用 drawRect、setNeedsDisplay 和 layoutSubViews