IBDesignable class drawing UIImage not showing in storyboard

I developed a user controller in Xcode that draws itself based on what state it is in. In one state, the controller displays the image, calling myImage?.draw(in: rect)inside the overwritten function draw(_ rect: CGRect).

The image is displayed correctly in the application, but is not in the storyboard. . To illustrate this, I added a Bezier ring as part of the same jitter function that appears in both the application and the storyboard:

The controller displayed in the application

Controller displayed in storyboard

Having studied the problem, I believe that this may be due to the fact that the image is optional. However, explicitly expanding it (i.e., the Call myImage!.draw(in: rect)causes the automatic layout of the storyboard to fail:

error: IB Designables: Failed to render and update auto layout status for SermonViewController (1zk-bD-8it): The agent crashed

I have exhausted the entire implementation of the class:

import UIKit

@IBDesignable class DownloadIndicatorControl: UIView {

    let requestDownloadImage = UIImage(named: "requestDownloadImage")
    let lineWidth: CGFloat = 3.0
    override func draw(_ rect: CGRect) {

        // Draw Image
        requestDownloadImage?.draw(in: rect)

        // Draw ring around image
        let radius: CGFloat = fmin(self.bounds.width, self.bounds.height) / 2 - lineWidth / 2
        let center: CGPoint = CGPoint(x: self.bounds.size.width / 2, y: self.bounds.size.height / 2)
        let disk: UIBezierPath = UIBezierPath()
        disk.lineWidth = lineWidth
        disk.addArc(withCenter: center,
                    radius: radius,
                    startAngle: CGFloat(-Double.pi / 2),
                    endAngle: CGFloat(2 * Double.pi - Double.pi/2),
                    clockwise: true)
        disk.stroke()
    }

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

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

Is there anything I can do to display the image in the storyboard and is there a way to explicitly expand the image without constantly changing the storyboard?

+4
source share
1 answer

The UIImage (named :) method uses the main package, but the Builder interface loads resources differently.

Try the following:

UIImage (named: at: compatibleWith :)

import UIKit

@IBDesignable class DownloadIndicatorControl: UIView {

var requestDownloadImage: UIImage?
let lineWidth: CGFloat = 3.0

override func draw(_ rect: CGRect) {

    // Draw Image
    requestDownloadImage?.draw(in: rect)

    // Draw ring around image
    let radius: CGFloat = fmin(self.bounds.width, self.bounds.height) / 2 - lineWidth / 2
    let center: CGPoint = CGPoint(x: self.bounds.size.width / 2, y: self.bounds.size.height / 2)
    let disk: UIBezierPath = UIBezierPath()
    disk.lineWidth = lineWidth
    disk.addArc(withCenter: center,
                radius: radius,
                startAngle: CGFloat(-Double.pi / 2),
                endAngle: CGFloat(2 * Double.pi - Double.pi/2),
                clockwise: true)
    disk.stroke()
}

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

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

override func prepareForInterfaceBuilder() {
    super.prepareForInterfaceBuilder()
    self.setup()
}

internal func setup() {
    let bundle = Bundle(for: DownloadIndicatorControl.self)
    requestDownloadImage = UIImage(named: "download", in: bundle, compatibleWith: nil)
}
}

enter image description here

+3
source

Source: https://habr.com/ru/post/1680749/


All Articles