首页 > 解决方案 > 将 Sprite 添加到导致 EXC_BAD_ACCESS 的场景

问题描述

所以我找不到适合我的问题的好答案。我正在 iOS 上创建一个 SpriteKit 游戏。我只是要给你们一个我的设置的快速概述,然后再解决这个问题。我认为这是解释这一点的最佳方式。

设置:

基本上在我的 didMove(to view:) 方法中,我调用了两个辅助函数:setupNodes() 和 setupLevel()。这些函数所做的是将不同的场景和 SKSpriteNodes 加载到内存中,然后将它们添加到场景中。这是我用来执行此操作的代码:

 func setupNodes(){
    doubleVent = (loadForegroundOverlayTemplate("DoubleVent").copy()  as! SKSpriteNode)
}

func loadForegroundOverlayTemplate(_ fileName: String) -> SKSpriteNode{
    let overlayScene = SKScene(fileNamed: fileName)!
    let overlayTemplate = overlayScene.childNode(withName: "ForegroundOverlay")!.copy() as! SKSpriteNode
    return overlayTemplate 
}

这现在存储了一个名为“ForegroundOverlay”的 SKNode 的子场景。然后我将它传递给一个名为“createForegroundOverlay()”的函数,如下所示:

let overlaySprite = doubleVent
createForegroundOverlay(doubleVent)

然后“createForegroundOverlay”将存储在 doubleVent 中的 SKSpriteNode 添加到场景中,如下所示:

 func createForegroundOverlay(_ overlayTemplate: SKSpriteNode) {
    let foregroundOverlay = overlayTemplate.copy() as? SKSpriteNode
    lastOverlayPosition.x = lastOverlayPosition.x + (lastOverlayWidth + ((foregroundOverlay?.size.width)!)/2)

    lastOverlayWidth = (foregroundOverlay?.size.width)!/2.0
    foregroundOverlay?.position = lastOverlayPosition

    //TESTING PURPOSES
    if TESTING_NODE_POS{
        print("The last overlay position x:\(lastOverlayPosition.x), y:\(lastOverlayPosition.y)")
        print("The last overlay width is \(lastOverlayWidth)")
        print("Adding a foreground overlay \(count)")
        count += 1
    }

    //TESTING PURPOSES
    if TESTING_BOX_OUTLINE {
        let foregroundPos = foregroundOverlay?.position
        let boxLocation = foregroundOverlay?.childNode(withName: "Box1")?.position
        if boxLocation != nil {
            print("The location of the box \(String(describing: boxLocation))")
            print("The foregroundLocation is \(String(describing: foregroundPos))")
            print("last overlay position is \(lastOverlayPosition)")
        }
    }

    //add the foreground overlay as a child of the foreground node
    fgNode.addChild(foregroundOverlay!)

}

定位变量——lastOverlayPosition、lastOverlayWidth 等——只是我的 GameScene 类的属性,用于知道何时何地添加已传递的覆盖。

fgNode 是我从 GameScene.sks 文件中存储的一个节点,如下所示:

let worldNode = self.childNode(withName: "World")!
    bgNode = worldNode.childNode(withName: "Background")!
    bgCityNode = worldNode.childNode(withName: "BackgroundCity")
    cityBGOverlayTemplate = (bgCityNode.childNode(withName: "Overlay")!.copy() as! SKNode)
    cityOverlayWidth = bgCityNode.calculateAccumulatedFrame().width
    backgroundOverlayTemplate = (bgNode.childNode(withName: "Overlay")!.copy() as! SKNode)
    backgroundOverlayWidth = backgroundOverlayTemplate.calculateAccumulatedFrame().width
    fgNode = worldNode.childNode(withName: "Foreground")!

这也是在我的 setupNodes() 方法中完成的。

问题:

所以也许你们中的一些人已经看到了这个问题,但问题是当我启动我的游戏时它会崩溃并且我收到消息:

“线程 1:EXC_BAD_ACCESS:(代码 = 1,地址 = 0x78)”

每次发生崩溃时,它都是完全相同的消息。我想我明白错误在说什么。基本上有一个指针指向内存中的某个位置(0x78),那里什么都没有。因此,取消引用该指针显然会导致错误。这是我感到困惑的地方......这只发生在大约 50% 的时间里。当我运行并构建项目时,它每次都会成功构建,然后在 50% 的时间里崩溃并显示该错误消息。其次,这发生在最开始。这对我来说很奇怪,因为如何释放一些内存导致游戏一开始就出现错误的指针。此外,如果在启动时没有发生崩溃,那么除非在显示游戏结束场景后我重新加载场景时,否则不会发生崩溃,这与重新启动的游戏基本相同。

一段时间后,我将问题缩小到一行代码:

fgNode.addChild(foregroundOverlay!)

如果我将此行注释掉,则不会发生崩溃(我尝试构建和运行 50 次)。问题一定出在foregroundOverlay 变量上,该变量是使用本讨论设置部分中的代码设置的。所以我不知道如何解决这个问题......有什么想法吗?

PS 可能还值得注意的是,当我升级到 xCode 10.0 并且我考虑使用僵尸时,以这种方式将孩子添加到场景中才明显成为一个问题,但我认为这不会有帮助,因为崩溃只会发生在游戏启动时。

如果我在任何地方不清楚,请告诉我。

标签: iosswiftsprite-kitskspritenode

解决方案


推荐阅读