我在Swift游戏中遇到过UIButtons和UILabels的奇怪问题。用户在游戏中开始,并且在失败时被移动到游戏结束屏幕中。在这个游戏画面屏幕上,会显示他们的高分以及两个按钮,可以返回主菜单,也可以返回玩游戏。这就是问题出现的地方。随机地,当场景从游戏场景变回游戏场景时,游戏场景的按钮和标签有时不会消失。它们作为游戏剩余部分叠加的静态表示。
我不知道是什么原因导致它们在大部分时间内消失,然后随机决定在不同的时间停留。
以下是gameover场景的代码。到目前为止,我已尝试使用.removeFromSuperview(),。alpha = 0以及代码现在的方式删除按钮和标签.hidden = true。这些都不是100%的时间。我已经尝试了所有我能想到的东西,但我不知道是什么导致标签和按钮粘在一起。
import Foundation
import SpriteKit
import UIKit
class endScene : SKScene {
var RestartBtn : UIButton!
var scoreLabel = UILabel()
var highLabel = UILabel()
var menuButton = UIButton()
var Highscore : Int!
var HS : Int!
override func didMoveToView(view: SKView) {
RestartBtn = UIButton(frame: CGRect(x: 0, y: 0, width: view.frame.size.width/3, height: 30))
RestartBtn.center = CGPoint(x: view.frame.size.width / 2, y: view.frame.size.width/1.3)
RestartBtn.setTitle("Restart", forState: UIControlState.Normal)
RestartBtn.setTitleColor(UIColor.redColor(), forState: UIControlState.Normal)
RestartBtn.addTarget(self, action: Selector("Restart"), forControlEvents: UIControlEvents.TouchUpInside)
menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: view.frame.size.width/3, height: 30))
menuButton.center = CGPoint(x: view.frame.size.width/2, y: view.frame.size.width/4)
menuButton.setTitle("Main Menu", forState: UIControlState.Normal)
menuButton.setTitleColor(UIColor.redColor(), forState: UIControlState.Normal)
menuButton.addTarget(self, action: Selector("gotoMenu"), forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(menuButton)
self.view?.addSubview(RestartBtn)
self.scene?.size = CGSize(width: 640, height: 1136)
let bgImage = SKSpriteNode(imageNamed: "Background")
bgImage.zPosition = -1
bgImage.position = CGPointMake(self.size.width/2, self.size.height/2)
self.addChild(bgImage)
let ScoreDefault = NSUserDefaults.standardUserDefaults()
let Score = ScoreDefault.valueForKey("Score") as! NSInteger
let HighscoreDefault = NSUserDefaults.standardUserDefaults()
Highscore = HighscoreDefault.valueForKey("Highscore") as? NSInteger
if (Highscore != nil){
HS = Highscore
}
else {
HS = 0
}
scoreLabel.center = CGPoint(x: view.frame.size.width / 9, y: view.frame.size.width / 4)
scoreLabel.textColor = UIColor.redColor()
scoreLabel.font = UIFont.boldSystemFontOfSize(15)
scoreLabel.font = UIFont(name: "Avenir-Light" , size: 90)
scoreLabel.text = "\(Score)"
scoreLabel.sizeToFit()
highLabel.center = CGPoint(x: view.frame.size.width / 9, y: view.frame.size.width / 2)
highLabel.textColor = UIColor.redColor()
highLabel.font = UIFont.boldSystemFontOfSize(15)
highLabel.font = UIFont(name: "Avenir-Light" , size: 60)
highLabel.text = "\(HS)"
highLabel.sizeToFit()
self.view?.addSubview(scoreLabel)
self.view?.addSubview(highLabel)
}
func Restart(){
running = true
clearendScene()
changeSceneGame()
}
func clearendScene(){
menuButton.hidden = true
scoreLabel.hidden = true
highLabel.hidden = true
RestartBtn.hidden = true
}
func changeSceneGame(){
self.scene!.view!.presentScene(GameplayScene(), transition: SKTransition.crossFadeWithDuration(0.8))
}
func changeSceneMenu(){
self.scene!.view?.presentScene(GameScene(), transition: SKTransition.crossFadeWithDuration(0.8))
}
func gotoMenu(){
clearendScene()
changeSceneMenu()
}
}
This is a screenshot of the overlay bug happening.
This is a screenshot of how the game is supposed to look on the gameplay scene.
答案 0 :(得分:0)
根据经验,我可能会建议您尽可能地隐藏这些按钮。我注意到你将它们隐藏在sortedScene方法中并将该方法嵌入到restart和goToMenu中。但是,在你调用转换之前,你应该调用clearScene应该是正确的。
例如:
func changeSceneGame(){
clearEndScene()
self.scene!.view!.presentScene(GameplayScene(), transition: SKTransition.crossFadeWithDuration(0.8))
}
答案 1 :(得分:0)
你的endScene可能被呈现两次(或者出于某种原因,didMoveToView会被调用两次)吗?
编写代码的方式,endScene的第二个演示文稿将创建一组新按钮并丢失它们的跟踪,只留下视图保存对它们的引用。
修复问题的一种懒惰方法是在didMoveToView的开头隐藏两个按钮。由于您要创建变量的空实例,因此这应该可以在第一次使用。
(你确实意识到每次出现endScene时你都会泄露这些按钮吗?)
[编辑]
我认为懒惰的方式不起作用,因为第一次,UIButton()的实例并没有连接到任何东西。
你不需要懒惰并修复设计。
1)您的按钮变量不应在其声明中创建空实例。
2)除非你在某些时候从视图中删除按钮,否则不应每次在didMoveToView中创建按钮的新实例(见下文)。您的代码每次都会向视图添加新的按钮对象,并且永远不会释放它们。
3)当你做RestartBtn = UIButton时(框架:CG ......你正在丢失对你添加到视图中的前一个按钮的引用。这就是为什么,第二次调用didMoveToView而不通过Restart()或gotoMenu ()将显示按钮对象。
4a)如果你想继续在didMoveToView()中添加按钮,请使用removeFromSuperview()在func willMoveFromView()的覆盖中从超级视图中删除它们。
4b)如果你只想添加它们一次,只使用它们的隐藏属性来显示/隐藏它们。使你的按钮变量静态,将它们初始化为nil并且只创建和添加它们一次(即当调用didMoveToView()时变量为nil)。
注意:因为有些东西会两次出现你的endScene,所有这些都可能没有实际意义,可能无法解决问题。也许您应该在didMoveToView的开头设置一个断点,并在第一次和第二次调用时检查调用堆栈。这应该揭示第二个呼叫来自何处(或者它可能是第一个无关的呼叫)。
答案 2 :(得分:0)
我在游戏中遇到了类似的问题。所以我设置了约束,初始化我的场景(有UIButton
)并在override func viewWillLayoutSubviews()
中展示它。出于某种原因,此函数被调用两次。正如Alain T.所说,因此存在内存泄漏。
要解决此问题,我移动了所有代码以初始化场景并将其显示为viewDidLoad()
并将override func viewWillLayoutSubviews()
更改为
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
}
它有效!按钮消失了!