SpriteBuilder Swift 代码连接无引用和释放问题
SpriteBuilder Swift code connections nil reference and deallocation issues
我正在使用 Swift (XCode 7.2.1) 和 SpriteBuilder (1.4.9) 创建游戏。但是,我在 CCB 文件和 Swift classes 之间创建代码连接时遇到了一些问题。我按照网上的教程在SpriteBuilder中添加了一个doc root var code connection name,然后在class中设置了相应的属性作为private weak var m_myVar: MyClass!
。但是,每当我尝试访问 属性 时,我都会得到一个 nil
引用。如果我从代码连接中删除 weak
属性,那么我可以访问 属性,但是当场景被销毁时,我会收到重新分配问题,例如使用 CCDirector.shareDirector().replaceScene()
方法导航到新场景。
在我的特定情况下,我在 SpriteBuilder 中有一个 MainScene
,其中包含以下节点层次结构:CCNode
-> CCNodeGradient
-> Tile
。其中 Tile
CCNode
的子 class 在不同的 CCB 文件中定义并且具有 doc root var
代码连接名称 m_levelLabel
,它映射到 private weak var m_levelLabel: Tile!
属性 的 MainScene
class。
Tile
class 有 2 个 CCSprite9Slice
类型的属性 m_background
和 CCLabelTTF
类型的 m_label
,它们都是映射的Tile
Swift class 中的 private weak var
属性。
当 MainScene
加载时,我尝试使用以下代码在 m_levelLabel
上设置一些属性:
internal func didLoadFromCCB() {
m_levelLabel.setValue("2");
}
和Tile.setValue
在Tile
class中定义为:
internal func setValue(value: String) {
m_label.string = value;
}
但是当 setValue
方法执行时 m_label
属性 是 nil
所以 fatal error: unexpectedly found nil while unwrapping an Optional value
发生了。这很奇怪,因为我在 MainScene
class 中的代码连接工作正常,因为我能够调用 m_levelLabel.setValue
.
有趣的是,如果我将 Tile
class 中的属性更改为定义为强引用,例如:
private var m_label: CCLabelTTF!;
然后代码执行正常,标签的值在 MainScene
加载时更新。但是,当我尝试离开 MainScene
并出现错误 malloc: *** error for object 0x7a9f3200: pointer being freed was not allocated
时,应用程序现在崩溃了,这听起来像是在破坏 Tile
[=] 中的强大属性时出现问题82=] 归 MainScene
.
所有
这里可能发生了什么?在 Swift 中定义代码连接的正确方法是什么?请注意,我在控制台中没有收到有关缺少代码连接属性的警告。
这里是 MainScene
和 Tile
class 的完整参考:
Main.swift
import Foundation
internal class MainScene: CCScene {
internal func didLoadFromCCB() {
m_levelLabel.setValue("1");
m_progressLabel.setValue("0%");
}
internal func play() {
let gameplayScene: CCScene = CCBReader.loadAsScene("Gameplay/GameplayScene");
CCDirector.sharedDirector().replaceScene(gameplayScene);
}
internal func levelSelection() {
print("Pressed level selection");
}
internal func progress() {
print("Pressed progress button");
}
private weak var m_playButton: CCButton!;
private weak var m_levelSelectionButton: CCButton!;
private weak var m_progressButton: CCButton!;
private weak var m_levelLabel: Tile!;
private weak var m_progressLabel: Tile!;
}
Tile.swift
import Foundation
internal class Tile : CCNode {
internal var value: String? {
return m_label?.string;
}
internal func setValue(value: String) {
m_label.string = value;
}
private weak var m_label: CCLabelTTF!;
private weak var m_background: CCSprite9Slice!;
}
所以事实证明,要使代码连接始终有效,它们必须具有 internal
可访问性而不是 private
。例如。
internal weak var m_label: CCLabelTTF!;
而不是
private weak var m_label: CCLabelTTF!;
我不确定为什么 private
在某些情况下有效,但在其他情况下却无效,很遗憾我无法正确封装这些数据。我想这要么是由于 SpriteBuilder 库中的错误,要么是由于 Swift 语言的限制。
我正在使用 Swift (XCode 7.2.1) 和 SpriteBuilder (1.4.9) 创建游戏。但是,我在 CCB 文件和 Swift classes 之间创建代码连接时遇到了一些问题。我按照网上的教程在SpriteBuilder中添加了一个doc root var code connection name,然后在class中设置了相应的属性作为private weak var m_myVar: MyClass!
。但是,每当我尝试访问 属性 时,我都会得到一个 nil
引用。如果我从代码连接中删除 weak
属性,那么我可以访问 属性,但是当场景被销毁时,我会收到重新分配问题,例如使用 CCDirector.shareDirector().replaceScene()
方法导航到新场景。
在我的特定情况下,我在 SpriteBuilder 中有一个 MainScene
,其中包含以下节点层次结构:CCNode
-> CCNodeGradient
-> Tile
。其中 Tile
CCNode
的子 class 在不同的 CCB 文件中定义并且具有 doc root var
代码连接名称 m_levelLabel
,它映射到 private weak var m_levelLabel: Tile!
属性 的 MainScene
class。
Tile
class 有 2 个 CCSprite9Slice
类型的属性 m_background
和 CCLabelTTF
类型的 m_label
,它们都是映射的Tile
Swift class 中的 private weak var
属性。
当 MainScene
加载时,我尝试使用以下代码在 m_levelLabel
上设置一些属性:
internal func didLoadFromCCB() {
m_levelLabel.setValue("2");
}
和Tile.setValue
在Tile
class中定义为:
internal func setValue(value: String) {
m_label.string = value;
}
但是当 setValue
方法执行时 m_label
属性 是 nil
所以 fatal error: unexpectedly found nil while unwrapping an Optional value
发生了。这很奇怪,因为我在 MainScene
class 中的代码连接工作正常,因为我能够调用 m_levelLabel.setValue
.
有趣的是,如果我将 Tile
class 中的属性更改为定义为强引用,例如:
private var m_label: CCLabelTTF!;
然后代码执行正常,标签的值在 MainScene
加载时更新。但是,当我尝试离开 MainScene
并出现错误 malloc: *** error for object 0x7a9f3200: pointer being freed was not allocated
时,应用程序现在崩溃了,这听起来像是在破坏 Tile
[=] 中的强大属性时出现问题82=] 归 MainScene
.
这里可能发生了什么?在 Swift 中定义代码连接的正确方法是什么?请注意,我在控制台中没有收到有关缺少代码连接属性的警告。
这里是 MainScene
和 Tile
class 的完整参考:
Main.swift
import Foundation
internal class MainScene: CCScene {
internal func didLoadFromCCB() {
m_levelLabel.setValue("1");
m_progressLabel.setValue("0%");
}
internal func play() {
let gameplayScene: CCScene = CCBReader.loadAsScene("Gameplay/GameplayScene");
CCDirector.sharedDirector().replaceScene(gameplayScene);
}
internal func levelSelection() {
print("Pressed level selection");
}
internal func progress() {
print("Pressed progress button");
}
private weak var m_playButton: CCButton!;
private weak var m_levelSelectionButton: CCButton!;
private weak var m_progressButton: CCButton!;
private weak var m_levelLabel: Tile!;
private weak var m_progressLabel: Tile!;
}
Tile.swift
import Foundation
internal class Tile : CCNode {
internal var value: String? {
return m_label?.string;
}
internal func setValue(value: String) {
m_label.string = value;
}
private weak var m_label: CCLabelTTF!;
private weak var m_background: CCSprite9Slice!;
}
所以事实证明,要使代码连接始终有效,它们必须具有 internal
可访问性而不是 private
。例如。
internal weak var m_label: CCLabelTTF!;
而不是
private weak var m_label: CCLabelTTF!;
我不确定为什么 private
在某些情况下有效,但在其他情况下却无效,很遗憾我无法正确封装这些数据。我想这要么是由于 SpriteBuilder 库中的错误,要么是由于 Swift 语言的限制。