我试图创建一个我可以调用的函数来更新我的UILabel scoreLabel.text
。但是,每当我尝试更改它时,我都会收到错误消息。让我感到困惑的是,在viewDidLoad()
内更改错误时我没有收到错误。其他地方都会返回以下错误:
在控制台中我也收到错误:
致命错误:在解包可选值时意外发现nil。
所以我所能相信的是,在调用我的函数来更新文本时,视图还没有加载UILabel。但我确定只有在视图已加载后才会调用此函数。
我已经检查/试过的事情:
scoreLabel.text
和self.scoreLabel.text
我也很肯定在changeTextLabel
加载到内存后调用scoreLabel
。但是我的错误似乎又说了。
这是我的代码的完整标记。为了便于阅读,我删除了一些不相关的详细信息:
import UIKit
import SpriteKit
class GameViewController: UIViewController {
@IBOutlet weak var scoreLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
//This is where all my other code was
print(scoreLabel.text)
scoreLabel.text = "Testing" //This line can be run
}
func changeTextLabel() {
print("changeTextLabel called")
if self.scoreLabel != nil {
self.scoreLabel.text = "yay"
} else {
print("scoreLabel is nil") //This is called every time
}
}
}
感谢您的时间
修改 GameScene.swift
这只是应该关注的部分
func projectileDidCollideWithMonster(projectile: SKSpriteNode, monster: SKSpriteNode) {
print("Hit")
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let object = storyBoard.instantiateViewController(withIdentifier: "GameViewController") as! GameViewController
object.changeTextLabel()
projectile.removeFromParent()
monster.removeFromParent()
}
答案 0 :(得分:1)
问题出在这一行,
let game = GameViewController()
game.changeTextLabel()
您应该使用XIB或Storyboard创建GameViewController对象。
在你的情况下,它只是使用.swift文件创建对象,正式类。
您应该使用与scoreLabel
具有IBOutlet连接的View创建对象。
尝试(如果使用故事板),
let storyboard = UIStoryboard(name: "YourStoryBoard", bundle: nil)
let gameVC = storyboard.instantiateViewController(withIdentifier: "GameViewController") as! UIViewController
或(如果使用 XIB )
var gameVC = GameViewController(nibName: "GameViewController", bundle: nil)
使用以下(Ref),
更新changeTextLabel
func changeTextLabel() {
print(self.view)
print("changeTextLabel called")
if self.scoreLabel != nil {
self.scoreLabel.text = "yay"
} else {
print("scoreLabel is nil") //This is called every time
}
}
答案 1 :(得分:1)
我不完全了解您的项目设置,但您的方法看起来很复杂,而不是您应该在SpriteKit游戏中做什么。所以我不认为告诉你如何解决当前的问题是一个好主意。
您应该直接在相关的SKScene中使用SpriteKit API(SKLabelNodes,SKSpriteNodes,SKNodes等)创建UI,例如标签,按钮等。
你的GameViewController应该只能真正处理呈现SKScenes。所以除了加载第一个SKScene之外,旁边应该没有代码。
如果您有多个SKScenes(MenuScene,ShopScene,SettingScene等),您的方法将会崩溃,因为分数标签将显示在所有SKScenes中。 GameViewController提供了所有的SKScenes,因此在所有SKscenes中添加到GameViewController中的是什么。这意味着您必须为每个场景删除/添加标签和其他UI,这将是混乱的。
因此,要创建乐谱标签,您应该直接在相关场景中执行此操作。我喜欢使用lazy var方法将标签的设置代码保存在同一位置。
class GameScene: SKScene {
lazy var scoreLabel: SKLabelNode = {
let label = SKLabelNode(fontNamed: "HelveticaNeue")
label.text = "SomeText"
label.fontSize = 22
label.fontColor = .yellow
label.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
return label
}()
override func didMove(to view: SKView) {
addChild(scoreLabel)
}
}
您可以直接在碰撞代码中直接更新。
scoreLabel.text = "NewText"
现在,当您从1 SKScene更改为另一个SKScene时,您不必担心删除此标签,SpriteKit会为您执行此操作。
您也可以使用xCodes级别编辑器直观地添加此标签,类似于故事板。这让我想到了最后的建议,即SpriteKit游戏中并没有真正使用故事板。故事板适用于ViewControllers,在SpriteKit中,您正在使用SKScenes。
希望这有帮助
答案 2 :(得分:0)
之所以发生这种情况,是因为你没有在任何其他函数中获得标签记忆。这是因为有很多原因。
一个原因可能是@IBOutlet弱var scoreLabel:UILabel! 尝试创建一个强大的变量出口。
@IBOutlet strong var scoreLabel: UILabel!
第二个原因可能是您在标签获取内存之前调用changeTextLabel。所以稍后再打电话。
答案 3 :(得分:0)
替换此行
self.scoreLabel.text = "yay"
使用
self.scoreLabel?.text = "yay"
答案 4 :(得分:0)
进行这些更改,然后重试:
{{1}}