更改UILabel的文本只能在viewDidLoad()中使用

时间:2016-11-08 05:33:16

标签: ios swift sprite-kit uikit uilabel

我试图创建一个我可以调用的函数来更新我的UILabel scoreLabel.text。但是,每当我尝试更改它时,我都会收到错误消息。让我感到困惑的是,在viewDidLoad()内更改错误时我没有收到错误。其他地方都会返回以下错误:

Imgur Link

在控制台中我也收到错误:

  

致命错误:在解包可选值时意外发现nil。

所以我所能相信的是,在调用我的函数来更新文本时,视图还没有加载UILabel。但我确定只有在视图加载后才会调用此函数。

我已经检查/试过的事情:

  • 我的IBOutlet已正确连接
  • 我的职能被称为
  • 同时使用scoreLabel.textself.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()
}

5 个答案:

答案 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}}