【问题标题】:How to refresh/redraw/reload a UIGraphicsImageRenderer in iOS with Swift如何使用 Swift 在 iOS 中刷新/重绘/重新加载 UIGraphicsImageRenderer
【发布时间】:2018-02-15 03:53:48
【问题描述】:

我有一个自定义的UIView 类,它使用UIGraphicsImageRenderer 绘制一些线条,并且我有一些滑块来更改用于绘制线条的点,但这样做不会删除旧线条,它只是绘制新线条那些在他们之上的。我尝试在方法的顶部和底部附近添加self.setNeedsDisplay(),但都没有任何区别。

我从 hackingwithswift project 27 中获得了如何使用 UIGraphicsImageRenderer 的基本概念——在那个项目中,他使用 switch 语句调用不同的函数来绘制不同的东西,这似乎可以很好地清除和重绘东西。

我也试过var clearsContextBeforeDrawing: Bool = true,但我认为我没有正确使用它,我在文档中找到了它。

我还在setNeedsDisplay 文档中看到它说“您应该使用此方法请求仅在视图的内容或外观发生变化时重绘视图。如果您只是更改视图的几何形状,视图通常不会重绘”——我猜“视图的几何”是指转换(缩放/平移/旋转)之类的东西?

func drawLines(pointList: [CGPoint],
               cycle: Bool = false,
               lineColor: CGColor = UIColor.blue.cgColor,
               fillColor: CGColor = UIColor.clear.cgColor) {

//        self.setNeedsDisplay()
    let renderer = UIGraphicsImageRenderer(size: CGSize(width: 728, height: 984))
//        var clearsContextBeforeDrawing: Bool = true
    let img = renderer.image { ctx in
        ctx.cgContext.move(to: pointList[0])

        for v in pointList.dropFirst() {
            ctx.cgContext.addLine(to: v)
        }

        ctx.cgContext.setStrokeColor(lineColor)
        ctx.cgContext.strokePath()
    }

    let iv = UIImageView(image:img)
    iv.frame.origin = CGPoint(x: 0, y: 0)
    self.addSubview(iv)
//        self.setNeedsDisplay()
}

【问题讨论】:

    标签: ios swift swift3 uiview


    【解决方案1】:

    每次调用drawLines() 时,您都会添加一个新的UIImageView。根据您的代码编写方式,每个图像视图都有清晰的背景……因此您会看到“线条”相互叠加。

    你应该一个 UIImageView 已经添加到self(我们称之为theDrawingImageView),然后将你的函数更改为以:

        //let iv = UIImageView(image:img)
        //iv.frame.origin = CGPoint(x: 0, y: 0)
        //self.addSubview(iv)
    
        theDrawingImageView.image = img
    }
    

    编辑:这是一个完整的演示。您可以直接在 Playground 页面中运行它。

    它创建一个视图控制器并添加一个UIButton 和一个UIImageView。每次点击按钮时,将生成一组 12 个随机点并用于在新的UIImage 上绘制线条,然后用于设置图像视图的.image 属性。

    import UIKit
    import PlaygroundSupport
    
    class TestViewController : UIViewController {
    
    
        let theDrawingImageView: UIImageView = {
            let v = UIImageView()
            v.backgroundColor = UIColor.lightGray
            v.translatesAutoresizingMaskIntoConstraints = false
            return v
        }()
    
        let btn: UIButton = {
            let b = UIButton()
            b.setTitle("Tap to Draw Lines", for: .normal)
            b.backgroundColor = .red
            b.translatesAutoresizingMaskIntoConstraints = false
            return b
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            view.backgroundColor = UIColor(red: 0.25, green: 0.5, blue: 1.0, alpha: 1.0)
    
            // add button and image view to self.view
            self.view.addSubview(btn)
            self.view.addSubview(theDrawingImageView)
    
            // button position
            btn.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
            btn.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 20.0).isActive = true
    
            // image view position
            theDrawingImageView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
            theDrawingImageView.topAnchor.constraint(equalTo: btn.bottomAnchor, constant: 20.0).isActive = true
    
            // image view width and height
            theDrawingImageView.widthAnchor.constraint(equalToConstant: 300.0).isActive = true
            theDrawingImageView.heightAnchor.constraint(equalToConstant: 300.0).isActive = true
    
            // add a target for the button tap
            btn.addTarget(self, action: #selector(btnTapped(_:)), for: .touchUpInside)
    
        }
    
        // simple random number function
        func random(_ range:Range<Int>) -> Int {
            return range.lowerBound + Int(arc4random_uniform(UInt32(range.upperBound - range.lowerBound)))
        }
    
        func btnTapped(_ sender: Any) {
    
            var pts = [CGPoint]()
    
            let maxX = Int(theDrawingImageView.bounds.size.width)
            let maxY = Int(theDrawingImageView.bounds.size.height)
    
            // generate a set of 12 random points
            for _ in 1...12 {
                let x = random(0..<maxX)
                let y = random(0..<maxY)
                let pt = CGPoint(x: x, y: y)
                pts.append(pt)
            }
    
            drawLines(imageView: theDrawingImageView, pointList: pts)
    
        }
    
        func drawLines(imageView: UIImageView,
                       pointList: [CGPoint],
                       cycle: Bool = false,
                       lineColor: CGColor = UIColor.blue.cgColor,
                       fillColor: CGColor = UIColor.clear.cgColor) {
    
            let renderer = UIGraphicsImageRenderer(size: imageView.bounds.size)
    
            // this creates a new UIImage and draws lines on it
            let img = renderer.image { ctx in
    
                ctx.cgContext.move(to: pointList[0])
    
                for v in pointList.dropFirst() {
                    ctx.cgContext.addLine(to: v)
                }
    
                ctx.cgContext.setStrokeColor(lineColor)
                ctx.cgContext.strokePath()
    
            }
    
            // set the image view's .image to the new image with the lines drawn on it
            imageView.image = img
        }
    
    }
    
    let vc = TestViewController()
    PlaygroundPage.current.liveView = vc
    

    【讨论】:

    • 抱歉,我还没有回复或接受您的回答——我还没有设法让它工作。我理解你所说的我如何在每次调用时创建一个新的UIImageView,但我似乎无法确切地弄清楚如何初始化theDrawingImageView。我用public var theDrawingImageView: UIImageView 声明它,然后尝试添加init(image: UIImageView?) { self.theDrawingImageView = image super.init(image: theDrawingImageView) 之类的东西我得到各种错误(在这种情况下没有可用的重载)。很明显,我不明白自己在做什么。
    • @Cody - 我用一个可以在操场页面中运行的完整示例编辑了我的答案。希望这会让它更清楚。
    • 我让操场工作,所以我想我应该能够理解它!也许是因为我最近更新到 Xcode 9,但它让我在 btnTapped 方法之前添加了一个 @objc。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    • 2014-10-23
    • 2016-06-09
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    相关资源
    最近更新 更多