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) }
应该做的伎俩.