草庐IT

ios - SpriteKit 在转换到新场景时收到有关 UIElements 的错误

coder 2023-09-04 原文

你好,我正在使用 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(例如按钮、 slider 和标签)导致了此问题。但是我将它们移到了 didMoveToView 函数中,所以我很困惑为什么它们仍然抛出错误,因为它们在“后台线程”中。

还有一点奇怪的是,这些并不是 fatal error 。我的控制台突然爆炸,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, UserId: self.mySettings.UserId, 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, width: self.size.width*0.3, 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, y: 10, width: self.size.width*0.3, height: 60)
        PowerSlider.frame = CGRect(x: self.size.width * 0.65, y: self.size.height*0.55, width: self.size.height*0.7, 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, width: self.size.width*0.3, 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, y: self.size.height-80, width: self.size.width*0.3, height: 60)
        PowerSlider.frame = CGRect(x: self.size.width * 0.525, y: self.size.height-30, width: self.size.width*0.45, height: 30)
    }

    self.view?.addSubview(AngleLabel)
    self.view?.addSubview(AngleSlider)
    self.view?.addSubview(PowerLabel)
    self.view?.addSubview(PowerSlider)

}

最佳答案

你这样做:

myURLRequests.getFleet(self, UserId: self.mySettings.UserId, enemy: false){ () -> () in
    myLoadingScene.end()
}

这可能会在 URL 请求完成后在后台线程上调用 myLoadingScene.end()end 设置loadCount,其中有一个启动新 View 的setter,self.view?.presentScene(newScene)

这是最后一 block 需要在主线程上运行。

假设您有一个方便的函数可以在主线程上运行一些东西:

func on_main_async (closure:()->()) {
    dispatch_async(dispatch_get_main_queue()) {
        closure()
    }
}

然后你可以将场景呈现代码更改为

on_main_async() { self.view?.presentScene(newScene) }

应该可以解决问题。

关于ios - SpriteKit 在转换到新场景时收到有关 UIElements 的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33677109/

有关ios - SpriteKit 在转换到新场景时收到有关 UIElements 的错误的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  3. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  4. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  5. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  6. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  7. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  8. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  9. ruby-on-rails - 错误 : Error installing pg: ERROR: Failed to build gem native extension - 2

    我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby​​'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe

  10. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

随机推荐