Swift/UIView/drawrect - как получить drawrect для обновления при необходимости

Я новичок в изучении Swift и пытаюсь запустить невероятно простое приложение. Все, что я пытаюсь сделать, это получить UIView.drawRect для обновления, когда я нажимаю кнопку. Он обновляет/рисует, когда приложение сначала загружается, а затем ничего после этого, что бы я ни пытался. Я пару раз бил головой об этом, и ничего не могу найти.

Я создал:

  • приложение с одним представлением

  • одна кнопка, связанная с контроллером представления как действие

  • новый класс, Test_View, подклассификация UIView

Код ViewController:

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.")
    }

}

Код Test_View:

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")            

    }

}

(Примечание: журнал обновляется каждый раз, когда я нажимаю кнопку, так что это не проблема. Это просто, что дисплей никогда не изменяется. Кроме того, я попытался рисовать прямоугольник со случайными координатами, поэтому он не обновляет его но я этого не вижу.)

Спасибо за любую помощь!

Ответ 1

Сначала вам нужно указать назначенный инициализатор для UIView (init с фреймом). Затем сделайте свой объект 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")

    }

}

Ответ 2

Вы вызываете setNeedsDisplay локальный экземпляр Test_View, созданный в функции Press_Button, а не один из вас 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.")
    }

    ...