SKLabelNode 相关的 EXC_BAD_ACCESS 崩溃

Posted

技术标签:

【中文标题】SKLabelNode 相关的 EXC_BAD_ACCESS 崩溃【英文标题】:SKLabelNode related EXC_BAD_ACCESS crash 【发布时间】:2017-03-22 12:13:02 【问题描述】:

我目前遇到了无法解决的崩溃问题。

在我正在开发的应用程序中,我有一个自定义类LabelNode: SKNode,它使用SKLabelNodeSKSpriteNode 在黑色方形背景上创建白色文本。使用下面的setText(newText: String) 函数为每一帧更新此标签

class LabelNode: SKNode 

private let textNode: SKLabelNode
private let backgroundNode: SKSpriteNode
private let padding: CGFloat

var width: CGFloat = 0
var height: CGFloat = 0
var horizontalAlignment = SKLabelHorizontalAlignmentMode.center

init(fontSize: CGFloat, text: String? = "A") 
    textNode = SKLabelNode(fontNamed: "Arial")
    textNode.zPosition = 1
    backgroundNode = SKSpriteNode(color: UIColor.black, size: CGSize(width: 0, height: 0))
    textNode.fontColor = UIColor.white
    textNode.fontSize = fontSize
    textNode.text = text
    textNode.verticalAlignmentMode = SKLabelVerticalAlignmentMode.top
    height = textNode.frame.size.height
    textNode.position.y = (height / 2)
    padding = 0.165 * height
    width = textNode.frame.size.width
    backgroundNode.size = CGSize(width: width + padding, height: height + padding)
    backgroundNode.position.x = textNode.frame.midX
    super.init()
    addChild(textNode)
    addChild(backgroundNode)


required init?(coder aDecoder: NSCoder) 
    fatalError("init(coder:) has not been implemented for LabelNode")


func setText(newText: String) 
    self.textNode.text = newText
    width = self.textNode.frame.size.width
    backgroundNode.size = CGSize(width: width + padding, height: height + padding)
    backgroundNode.position.x = textNode.frame.midX


func setFontColor(newFontColor: UIColor) 
    self.textNode.fontColor = newFontColor


func setAlignment(newAlignment: SKLabelHorizontalAlignmentMode) 
    self.textNode.horizontalAlignmentMode = newAlignment

我的应用程序不断以随机时间间隔抛出 EXC_BAD_ACCESS,有时还会在不同的线程上抛出不同的错误消息。有时 xcode 指向行

width = self.textNode.frame.size.width

但有时在线程 x 上的随机行,但上面的行在线程 y 中处于活动状态。

如果僵尸被激活但All Exceptions 断点和malloc_error_break 都被停用,我会在崩溃时得到以下终端输出

-[SKTexture dealloc]: message sent to deallocated instance 0x10bbaf70

po 0x10bbaf70 只给出输出

280735600

以及下面的堆栈跟踪

* thread #41: tid = 0x73287, 0x1d9ac4d0 CoreFoundation`___forwarding___ + 532, queue = 'com.apple.scenekit.renderingQueue.applicationName.GameView0x1478d2b0', stop reason = EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xdefe)
frame #0: 0x1d9ac4d0 CoreFoundation`___forwarding___ + 532
frame #1: 0x1d8d13d8 CoreFoundation`_CF_forwarding_prep_0 + 24
frame #2: 0x1cc25194 libobjc.A.dylib`objc_object::sidetable_release(bool) + 238
frame #3: 0x2b23ff0a SpriteKit`SKCSpriteNode::~SKCSpriteNode() + 38
frame #4: 0x2b23ff28 SpriteKit`SKCSpriteNode::~SKCSpriteNode() + 8
frame #5: 0x2b2204a2 SpriteKit`SKCLabelNode::rebuildText() + 134
frame #6: 0x2b2201b2 SpriteKit`SKCLabelNode::getBoundingBox() + 34
frame #7: 0x2b27d248 SpriteKit`-[SKNode frame] + 40
frame #8: 0x2b297928 SpriteKit`-[SKLabelNode frame] + 40
* frame #9: 0x000aea54 applicationName`LabelNode.setText(newText="9 555 m", self=0x15863970) -> () + 288 at LabelNode.swift:45

如果我使用All Exceptions 断点和malloc_error_break 激活运行,我不会得到任何终端输出和以下堆栈跟踪

* thread #21: tid = 0x7414f, 0x1cc24612 libobjc.A.dylib`objc_release + 2, queue = 'com.apple.scenekit.renderingQueue.applicationName.GameView0x177651b0', stop reason = EXC_BAD_ACCESS (code=1, address=0x2)
frame #0: 0x1cc24612 libobjc.A.dylib`objc_release + 2
frame #1: 0x2b23fefa SpriteKit`SKCSpriteNode::~SKCSpriteNode() + 22
frame #2: 0x2b23ff28 SpriteKit`SKCSpriteNode::~SKCSpriteNode() + 8
frame #3: 0x2b2204a2 SpriteKit`SKCLabelNode::rebuildText() + 134
frame #4: 0x2b2201b2 SpriteKit`SKCLabelNode::getBoundingBox() + 34
frame #5: 0x2b27d248 SpriteKit`-[SKNode frame] + 40
frame #6: 0x2b297928 SpriteKit`-[SKLabelNode frame] + 40
* frame #7: 0x00181a54 applicationName`LabelNode.setText(newText="4 033 m", self=0x17786cb0) -> () + 288 at LabelNode.swift:45

有谁知道这次崩溃背后的原因是什么,或者我可以采取哪些进一步的措施来阐明这一点?任何提示都会非常有帮助:)

【问题讨论】:

【参考方案1】:

您没有显示足够的代码来完全理解您的问题,从看起来您正在对 labelNode 进行子类化并试图在该标签后面放置一个 spriteNode 的样子?在我看来,这将是一个更简单的情况。

    class LabelNode : SKSpriteNode 

init(texture: SKTexture?, color: UIColor, size: CGSize, text: String) 

    super.init(texture: texture, color: color, size: size)


    let label = SKLabelNode(fontNamed: "Courier-Bold")
    label.fontSize = 50
    label.fontColor = SKColor.black
    label.position = CGPoint.init(x: 0.0, y: 0.0)
    label.zPosition = 1
    label.verticalAlignmentMode = .center
    label.text = text
    self.addChild(label)



required init?(coder aDecoder: NSCoder) 
    fatalError("init(coder:) has not been implemented")


       

创建一个自定义精灵节点类并直接在其上添加标签。

然后将其添加到视图中。

      let labelNode = LabelNode(texture: nil, color: .white, size: CGSize.init(width: 400, height: 100) , text: "Enter text")
    labelNode.position = CGPoint(x: self.frame.midX, y: self.frame.midY)

    self.addChild(labelNode)

【讨论】:

以上是关于SKLabelNode 相关的 EXC_BAD_ACCESS 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

为 SKLabelNode 设置背景颜色?

如何设置 SKLabelNode 的字体大小以适应固定大小(Swift)

将 SKLabelNode 设置为 SKSpriteNode Swift 的中心

带有 SKLabelNode 的文本工具包

将 SKLabelNode 添加到场景工具包视图

创建 SKLabelNode 时未命名的子节点?