Post marked as solved
Post marked as solved with 5 replies, 526 views
I've just spent a couple of hours zeroing in on a very weird bug. It seems that the Swift 5.9 compiler in XCode 15b4 is being overly-aggressive in clearing weak vars, compared to previous versions.
I have a method that returns an SKAction?.
In the debugger, I traced code and verified that the value it attempts to return is a
some : <SKMove: 0x280422b40>
However, the caller saves that value into a member which appears immediately after assignment nil
I tried adding a local variable for the return value, as seen below. That worked but
override func perform() -> Bool {
if cachedSKA == nil {
let xcodeBugWorkaround = gameAction.makeSKAction() // was assigning nil with xcode15b4
cachedSKA = xcodeBugWorkaround
// cachedSKA now shows in the debugger as non-nil
if let activeScene = tgTouchgram.mostRecentlyStartedPlaying?.activeSKScene,
let foundNode = referredNode(on: activeScene) {
cachedTarget = foundNode
}
}
// BUG - still fails at this point - cachedSKA appears nil again
guard let ska = cachedSKA, let targetNode = cachedTarget else { return true }
targetNode.run(ska)
return true
}
The problem appears to be because cachedSKA is a weak vars.
I am fairly certain it is being set to nil incorrectly.
Even though, within this method, the value is used, it is clearing the property as the sole holder of the object reference.
A fussy walkthrough reveals the compiler's changed behaviour is probably legal but certainly unexpected.
Working version, still keeping the property as weak:
override func perform() -> Bool {
var localSKA: SKAction? = cachedSKA
if localSKA == nil {
localSKA = gameAction.makeSKAction()
cachedSKA = localSKA
if let activeScene = tgTouchgram.mostRecentlyStartedPlaying?.activeSKScene,
let foundNode = referredNode(on: activeScene) {
cachedTarget = foundNode
}
}
guard let ska = localSKA, let targetNode = cachedTarget else { return true }
targetNode.run(ska)
return true
}