如何使用函数调用正确更新CGContext?

问题描述

我正在做一个射击游戏,其中一艘小飞船探索充满敌人等物品的8x8等级的房间。我目前正在尝试实施一张地图,向玩家显示他们已经去过的地方。我最初的实现很简单-我制作了一个自定义UIView,将其附加到我的Storyboard,并希望简单地绘制在地图上访问的所有新房间。我选择使用CGContext进行此操作,并在下面显示我的第一次尝试。

使用此代码,第一个updateMap调用可以完美工作-在播放器地图上以正确的颜色和位置绘制矩形。但是,尽管CGRect正确更新,但随后的任何调用似乎都不会画任何东西。如果取消注释PopContext(或删除PushContext),则会触发“找不到上下文”引发。虽然下面显示状态的代码不会显示“找不到上下文”,但也不会更新地图。

诚然,我对CGContext的理解很平淡,所以我认为我在这里只是一个概念上的错误。话虽这么说,我到底是在搞什么?

class MapView: UIView {


var x: Int!
var y: Int!
var drect: CGRect!

override func draw( _ frame: CGRect) {
    
    super.draw(frame)
    
    if let context: CGContext = UIGraphicsGetCurrentContext(){
        //UIGraphicsPopContext()
        context.setFillColor(red: 1.0,green: 1.0,blue: 1.0,alpha: 0.0);   //this is the transparent color
        context.setstrokeColor(red: 0.0,green: 0.0,blue: 100.0,alpha: 1.0);
        context.fill(drect);
        context.stroke(drect);    //this will draw the border
        context.addRect(drect)
        UIGraphicsPushContext(context)
    } else {
        print("Context not found")
        return
    }



}

public func updateMap(scene: GameScene){
    x = scene.current_xcoords
    y = scene.current_ycoords
    let w = self.frame.width
    let h = self.frame.height
    drect = CGRect(x: (w/50) + CGFloat(x)*w/8,y: (h/100) + CGFloat(y)*h/8,width: (h / 11),height: (h / 11))
    draw(self.frame)
}

}

解决方法

您不应直接调用draw()方法,而应调用setNeedsDisplay()layoutIfNeeded()

根据Apple docs

第一次显示视图或事件时调用此方法 发生使视图的可见部分无效的情况。你不应该 自己直接调用此方法。要使部分视图无效, 从而导致该部分被重绘,请调用setNeedsDisplay() 或使用setNeedsDisplay(_ :)方法。

因此您的代码成为

public func updateMap(scene: GameScene){
    x = scene.current_xcoords
    y = scene.current_ycoords
    let w = self.frame.width
    let h = self.frame.height
    drect = CGRect(x: (w/50) + CGFloat(x)*w/8,y: (h/100) + CGFloat(y)*h/8,width: (h / 11),height: (h / 11))
    setNeedsDisplay()
}