I have posted several times asking for help to resolve a conundrum involving the ability to invoke "needsDisplay = true" from a different class. I have done some tests and seem to have revealed some inconsistent behavior in Swift which I don't understand. As I said in previous posts, for some reason I haven't acquired a deep understanding of Apple's object oriented programming - my brain somehow can't wrap itself around a number of its concepts.
First, here is an outline of the class structure of my Mac app, leaving out unimportant details:
class GameViewController: NSViewController {
@IBOutlet weak var graph: GraphView!
@IBAction func h1_Slider(_ sender: NSSlider) {
h1_length = sender.floatValue
dodraw() // This is only here to make a point about - it is not used normally
}
func dodraw() {
graph.needsDisplay = true
return
}
<lots of other stuff to set up Metal drawing>
}
class Renderer: NSObject, MTKViewDelegate {
public var graphRef = GameViewController() //. Allows access to GameViewController from elsewhere
<lots of stuff to set up Metal>
func draw(in view: MTKView) { // Metal drawing loop
grafRef.dodraw() // this is supposed to cause GraphView to update its drawing
<this is where the Metal drawing is done>
}
}
class GraphView:NSView
{
override func draw(_ dirtyRect:CGRect) {
<This is where the Bezier drawing takes place in a View in the Storyboard View identified as an instance of GraphView
}
}
Basically, the inner loop of the Metal drawing, which occurs 60 times a second, calls the dodraw() method in the GameViewController via the reference graphRef. This should set the needsDisplay Bool to true in GraphView so that the graph can be drawn. Instead I get "Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value" with the graph underlined in red.
Here is the inconsistency, as I see it. If I replace the "needsDisplay = true" in the dodraw() method with a print("Q") and do nothing else, the letter Q is printed many times in the output window of Xcode. This shows that the graphRef link in Renderer is working fine. Likewise, if I put back the "graph.needsDisplay = true" and remove the dodraw() call in the Metal drawing loop, the graph is displayed while I move the slider in the GameViewController class. This shows that there seems to be no trouble unwrapping the Optional value in the "graph.needsDisplay = true" statement.
I consider this to be a very inconsistent behavior: I have no trouble invoking the needsDisplay = true command by appending a "graph." before it and I have no trouble referring to the dodraw() method from the Metal inner loop. Only trouble is I can't do these at the same time. What is going wrong? Is it a misconception about how Swift works?