Недопустимый контекст 0x0 в пользовательском uiview - дополнительный вопрос

Эта почта: недопустимый контекст 0x0 в пользовательском UIView ... должен был дать мне ключ для решения моей проблемы, но я не смог избежать ошибки недопустимого контекста. Были бы очень признательны за некоторые пояснения.

Я хочу рисовать линии в подпредставлении, представленном при загрузке ViewController. Для этого я создаю подкласс UIView, который похож на SplitCircleView, размещенный StartPlayer.

Чтобы запустить код, создайте новый проект и замените содержимое файла ViewController на:

import UIKit
@IBDesignable

class ViewController: UIViewController {
    let mySubViewInstance = SplitCircleView()

    override func viewDidLoad() {
        super.viewDidLoad()

        //let mySubViewInstance = SplitCircleView()
        mySubViewInstance.setNeedsDisplay(mySubViewInstance.frame)
    }
}

class SplitCircleView: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        //self.setNeedsDisplay()
        //draw(frame)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        //self.setNeedsDisplay()
        //draw(frame)
    }

    override func setNeedsDisplay(_ rect: CGRect) {
        self.backgroundColor = .clear

        drawSlice(rect: rect, startPercent: 87.5, endPercent: 37.5, color: .green)
        drawSlice(rect: rect, startPercent: 37.5, endPercent: 87.5, color: .red)
    }

    func drawSlice(rect: CGRect, startPercent: CGFloat, endPercent: CGFloat, color: UIColor) {
        let center = CGPoint(x: rect.origin.x + rect.width / 2, y: rect.origin.y + rect.height / 2)
        let radius = (min(rect.width, rect.height) / 2)
        let startAngle = startPercent / 100 * .pi * 2 - .pi
        let endAngle = endPercent / 100 * .pi * 2 - .pi
        let path = UIBezierPath()

        path.move(to: center)
        path.addArc(withCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
        path.close()
        color.setFill()
        path.fill()
    }
}

Как я могу избежать ошибки недопустимого контекста и нарисовать что-то в подпредставлении при загрузке ViewController?

0
0
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы должны переопределять draw, а не setNeedsDisplay.

override func draw(_ rect: CGRect) {
    self.backgroundColor = .clear

    drawSlice(rect: rect, startPercent: 87.5, endPercent: 37.5, color: .green)
    drawSlice(rect: rect, startPercent: 37.5, endPercent: 87.5, color: .red)
}

И настройку цвета фона нужно сделать только один раз, поэтому draw не совсем идеальное место для этой линии. Переместите его на init.

setNeedsDisplay указывает на необходимость обновления чертежа. Но на самом деле рисунок делает именно draw.

Ответ принят как подходящий

Есть два места, которые нужно исправить.

Вы создаете новое представление, поэтому вам нужно добавить в представление вашего viewController

 override func viewDidLoad() {
    super.viewDidLoad()

    let mySubViewInstance = SplitCircleView.init(frame: self.view.bounds)
    self.view.addSubview(mySubViewInstance)

  //  mySubViewInstance.setNeedsDisplay(mySubViewInstance.frame)
}

второй - рисовать функцию без использования setNeedsDisplay ();

override func draw(_ rect: CGRect) {

       self.backgroundColor = .clear
    drawSlice(rect: rect, startPercent: 87.5, endPercent: 37.5, color: .green)
    drawSlice(rect: rect, startPercent: 37.5, endPercent: 87.5, color: .red)
}

Таким образом, вы получите здесь свой красивый рисунок.

enter image description here

Спасибо тебе за пояснение. @rmadddy тоже спасибо за исправление вызова draw (). Очень помогает, но у меня все еще есть проблема, если я хочу указать размеры представления из viewDidLoad (). В этом случае SplitCircleView запускается с пользовательскими размерами, но draw () не вызывается. Когда draw () вызывается после команды .addSubview, входной аргумент возвращается к размерам супервизора. Как совместить инициализацию SplitCircleView и вызов функции?

cjg 14.09.2018 13:04

Это простая версия. вы можете рассмотреть возможность помещения splitcircleview в IB. а затем вы можете использовать автоматическое размещение для добавления ограничений. let mySubViewInstance = SplitCircleView () должен измениться на @IBOutlet var mySubViewInstance: SplitCircleView !. Затем свяжите его с объектом UIView. Теперь мы инициализируем его с помощью let mySubViewInstance = SplitCircleView.init (frame: self.view.bounds). Когда вы используете IB, он инициализируется вторым init: то есть init? (Coder aDecoder: NSCoder). Вам это не нужно, просто дайте понять разницу.

E.Coms 14.09.2018 14:08

Другие вопросы по теме