Swift / UIView / drawrect - 如何在需要时更新drawrect?

13

我刚开始学习Swift,尝试运行一个非常简单的应用程序。我只是想在按下按钮时更新UIView.drawRect。它会在应用程序首次加载时更新/绘制,然后无论我尝试什么都不会再更新。我已经连续几天苦思冥想,找不到任何可帮助我的东西。

我创建了:

  • 单视图应用程序

  • 一个按钮,作为操作链接到视图控制器

  • 一个新类,Test_View,继承自UIView

视图控制器代码:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        var f = Test_View()

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func Button_Pressed(sender: AnyObject) {
        var f = Test_View()
        f.setNeedsDisplay()
        NSLog("Button pressed.")
    }

}

查看代码测试:

class Test_View: UIView {

    override func drawRect(rect: CGRect) {
        let h = rect.height
        let w = rect.width
        var color:UIColor = UIColor.yellowColor()

        var drect = CGRect(x: (w * 0.25),y: (h * 0.25),width: (w * 0.5),height: (h * 0.5))
        var bpath:UIBezierPath = UIBezierPath(rect: drect)

        color.set()
        bpath.stroke()

        NSLog("drawRect has updated the view")            

    }

}

(注:每次我按下按钮时,日志都会更新,所以这不是问题。只是显示从未改变。此外,我已经尝试使用随机坐标绘制矩形,所以不是更新了但我没有看到它的问题。)

感谢任何帮助!

2个回答

19

首先,您需要为UIView指定一个指定的初始化程序(init with frame)。 然后将您的对象 f 设为类常量或变量(根据您的需求),以便在项目的范围内可以访问它。此外,您还必须将其添加为视图的子视图。 代码如下:

```swift let f = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) view.addSubview(f) ```
import UIKit

class ViewController: UIViewController {
    let f = Test_View(frame: CGRectMake(0, 0, 50, 50))

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(f)
    }

    @IBAction func buttonPressed(sender: UIButton) {
        f.setNeedsDisplay()
    }
}

class Test_View: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

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

    override func draw(_ rect: CGRect) {
        let h = rect.height
        let w = rect.width
        let color:UIColor = UIColor.yellow

        let drect = CGRect(x: (w * 0.25),y: (h * 0.25),width: (w * 0.5),height: (h * 0.5))
        let bpath:UIBezierPath = UIBezierPath(rect: drect)

        color.set()
        bpath.stroke()

        NSLog("drawRect has updated the view")

    }

}

1
非常感谢您提供如此全面的答案!回想起来,不像这样声明f似乎是显而易见的!有趣的是,这个实现确实有一个小问题:在加载时出现的矩形会一直停留,而在按下按钮后出现的矩形会一直出现直到下一次按下按钮,然后它就会消失并重新绘制。我认为这可能与视图/子视图设置有关...我会再多阅读一些相关资料! - Tom M
尝试在 drawRect: 中添加 super.drawRect(rect) - Ian
也许现在已经很晚了,而且我从未正式学习过计算机科学,但当我读到这段话时:“指定一个指定的初始化程序...然后将您的对象f设置为类常量...以便可以在项目范围内访问它。此外...将其作为您视图的子视图添加”。对我来说,这听起来像胡言乱语。如果您能够重写这个句子,就好像您正在向一个孩子(我)解释这些说明,您会如何解释这些说明? - Sebastian

3
您正在调用setNeedsDisplay,它是在Press_Button函数中实例化的Test_View的本地实例,而不是您需要创建的UIViewController中的实例(顺便说一下,在ViewDidLoad中创建它作为局部变量没有任何好处)。您可能希望将其创建为@IBOutlet,然后使用界面构建器定义一个实例以附加到该变量 - UIViewController如下所示:
class ViewController: UIViewController {
    @IBOutlet weak var instruction: UILabel?
    @IBOutlet weak var f: Test_View?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func Button_Pressed(sender: AnyObject) {
        f.setNeedsDisplay()
        NSLog("Button pressed.")
    }

    ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接