您好我正在使用
Swift的SpriteKit游戏,现在只有两个场景,一个加载场景和游戏场景.游戏场景到达数据库以在呈现之前获取信息.游戏场景中的一切都很棒.当我首先进入装载场景而不是直接进入游戏场景时,我遇到了问题.通过回调,我告诉加载场景,一旦完成数据库操作就会呈现游戏场景.然而,当我尝试呈现时,我得到了10个这样的大错误:
2015-11-12 09:48:33.880 SpaceAcademy[2373:764586] This application is
modifying the autolayout engine from a background thread,which can
lead to engine corruption and weird crashes. This will cause an
exception in a future release. (followed by a bunch of random info)
现在通过一些测试,我发现它是我的UIElement,例如按钮,滑块和标签,这些都是导致这种情况发生的.但是我将它们移动到了didMoveToView函数中,所以我很困惑为什么它们仍然会抛出错误,因为它们位于“后台线程”中.
还奇怪的是,这些都不是致命的错误.我的控制台刚刚爆炸,UIElements在延迟十秒后出现.其他奇怪的是,如果我点击我知道按钮应该是的位置,该功能仍然被调用,就像按钮实际上在那里一样.
我非常感谢摆脱控制台爆炸的解决方案,但更重要的是摆脱了UI元素出现的十秒延迟,谢谢!
代码设置场景
let skView = view as! SKView skView.showsFPS = false skView.showsNodeCount = false skView.ignoresSiblingOrder = true let scene = GameScene(size: view.bounds.size) scene.scaleMode = SKSceneScaleMode.ResizeFill let loading = LoadingScene(size: view.bounds.size,newScene: scene) skView.presentScene(loading,transition: SKTransition.crossFadeWithDuration(1)) scene.setEverythingUp(loading)
加载场景:
import Foundation import SpriteKit class LoadingScene:SKScene{ var newScene:SKScene! var oldCount = 0 var loadCount = 0{ didSet{ print(loadCount) if loadCount == 0{ if oldCount == 1{ self.view?.presentScene(newScene) } } oldCount = loadCount } } init(size: CGSize,newScene:SKScene) { self.newScene = newScene super.init(size: size) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func didMoveToView(view: SKView) { self.backgroundColor = UIColor.blackColor() let imageArray = [ SKTexture(imageNamed: "Loader/Loader1.png"),SKTexture(imageNamed: "Loader/Loader2.png"),SKTexture(imageNamed: "Loader/Loader3.png") ] let loader = SKSpriteNode(texture: imageArray[0]) let animation = SKAction.animateWithTextures(imageArray,timePerFrame: 0.33) loader.runAction(SKAction.scaleBy(0.25,duration: 0)) loader.zPosition = 100 loader.runAction(SKAction.repeatActionForever(animation)) loader.position = CGPointMake(self.size.width/2,self.size.height/2) self.addChild(loader) } func start(){ self.loadCount = self.loadCount + 1 } func end(){ self.loadCount = self.loadCount - 1 } }
来自GameScene的代码:
func setEverythingUp(myLoadingScene: LoadingScene){ let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults() var Id = 0 if let tempID = defaults.objectForKey("UserId") as? Int { Id = tempID }else{ print("newUser") defaults.setObject(0,forKey: "UserId") defaults.synchronize() } self.mySettings = Settings(UserId: Id) self.myURLRequests = URLRequests(thesettings: self.mySettings) ///////////call back system here,start() increments number of tasks waiting to finish,end() means a task is finished myLoadingScene.start() myURLRequests.getFleet(self,UserId: self.mySettings.UserId,enemy: false){ () -> () in myLoadingScene.end() } myLoadingScene.start() myURLRequests.getFleet(self,enemy: true){ () -> () in myLoadingScene.end() } self.backgroundColor = SKColor.blackColor() self.physicsWorld.contactDelegate = self self.physicsWorld.gravity = CGVector(dx: 0,dy: 0) addStars() self.anchorPoint = CGPoint(x:self.size.width/2,y:self.size.height/2) self.myCamera.position = CGPointMake(200,0) self.addChild(self.myCamera) self.camera = self.myCamera self.myAnchor.position = self.myCamera.position } override func didMoveToView(view: SKView) { print("in view") let pinch = UIPinchGestureRecognizer(target: self,action: Selector("PinchScale:")) let tap = UITapGestureRecognizer(target: self,action: Selector("Tap:")) let pan = UIPanGestureRecognizer(target: self,action: Selector("DragMove:")) self.view?.addGestureRecognizer(pinch) self.view?.addGestureRecognizer(tap) self.view?.addGestureRecognizer(pan) let fireButton = UIButton(type: .System) fireButton.setTitle("Fire!",forState: UIControlState.Normal) fireButton.titleLabel!.font = UIFont(name: "TrebuchetMS",size: 70) fireButton.sizeToFit() fireButton.frame = CGRect(x: self.size.width*0.5 - 80,y: 20,width: self.size.width*0.3,height: 30) fireButton.addTarget(self,action: Selector("FireButtonClicked"),forControlEvents: UIControlEvents.TouchUpInside) self.view?.addSubview(fireButton) let alternateControls = false let AngleLabel = UILabel() AngleLabel.text = "Angle" AngleLabel.font = UIFont(name: "TrebuchetMS",size: 30) AngleLabel.textColor = UIColor.blueColor() let AngleSlider = UiSlider() AngleSlider.addTarget(self,action: Selector("AngleSlided:"),forControlEvents: UIControlEvents.ValueChanged) AngleSlider.maximumValue = 90 AngleSlider.minimumValue = -90 AngleSlider.value = 0 AngleSlider.continuous = true let PowerLabel = UILabel() PowerLabel.text = "Power" PowerLabel.font = UIFont(name: "TrebuchetMS",size: 30) PowerLabel.textColor = UIColor.blueColor() let PowerSlider = UiSlider() PowerSlider.addTarget(self,action: Selector("PowerSlided:"),forControlEvents: UIControlEvents.ValueChanged) PowerSlider.maximumValue = 0.99 PowerSlider.minimumValue = 0.1 PowerSlider.value = 0.5 PowerSlider.continuous = true if alternateControls{ AngleLabel.frame = CGRect(x: self.size.width*0.05,y: 10,height: 60) AngleSlider.frame = CGRect(x: self.size.width * -0.05,y: self.size.height*0.55,width: self.size.height*0.7,height: 30) AngleSlider.transform = CGAffineTransformMakeRotation(CGFloat(M_PI) * 1.5) PowerLabel.frame = CGRect(x: self.size.width*0.7,height: 60) PowerSlider.frame = CGRect(x: self.size.width * 0.65,height: 30) PowerSlider.transform = CGAffineTransformMakeRotation(CGFloat(M_PI) * 1.5) }else{ AngleLabel.frame = CGRect(x: self.size.width*0.21,y: self.size.height-80,height: 60) AngleSlider.frame = CGRect(x: self.size.width * 0.025,y: self.size.height-30,width: self.size.width*0.45,height: 30) PowerLabel.frame = CGRect(x: self.size.width*0.71,height: 60) PowerSlider.frame = CGRect(x: self.size.width * 0.525,height: 30) } self.view?.addSubview(AngleLabel) self.view?.addSubview(AngleSlider) self.view?.addSubview(PowerLabel) self.view?.addSubview(PowerSlider) }
解决方法
你这样做:
myURLRequests.getFleet(self,enemy: false){ () -> () in myLoadingScene.end() }
一旦URL请求完成,可能会在后台线程上调用myLoadingScene.end(). end设置loadCount,它有一个启动新视图的setter,self.view?.presentScene(newScene)
这是需要在主线程上运行的最后一块.
假设你有一个方便的函数来在主线程上运行一些东西:
func on_main_async (closure:()->()) { dispatch_async(dispatch_get_main_queue()) { closure() } }
然后您可以将场景演示代码更改为
on_main_async() { self.view?.presentScene(newScene) }
应该做的伎俩.