【问题标题】:Assembly crash report when casting UIView to SKView将 UIView 转换为 SKView 时的程序集崩溃报告
【发布时间】:2014-08-28 16:12:54
【问题描述】:

我正在 SpriteKit 中制作一个简单的游戏,并且我正在尝试使用 UIKit 制作一个主菜单。我为主菜单创建了一个视图控制器,并为游戏创建了一个单独的控制器。每当按下播放按钮时,它就会切换到 Game 视图控制器,然后在那里呈现第一个场景。但是,每当它试图将游戏视图控制器的 UIView 投射到和 SKView 以能够呈现场景时,就会失败,并且崩溃报告是汇编,我不知道如何调试。我相信它会实例化游戏视图控制器两次,因为当我在 viewWillLayoutSubviews() 方法中放置一个 println() 时,它会打印两次。另一篇关于此的帖子说该类型在投射期间已经是 SKView ,导致它失败,在这种情况下,这可能意味着当它触发两次时,它会投射一次,然后再次尝试投射并失败。提前致谢!

这里是快速代码

import UIKit
import SpriteKit

class MenuViewController: UIViewController {
    let background = UIImageView(image: UIImage(named: "background.png"))
    let titleImg = UIImageView(image: UIImage(named: "title.png"))

    override func viewDidLoad() {
        background.frame = self.view.frame
        titleImg.frame = CGRectMake(0, 0, self.view.frame.width, 100)
        self.view.addSubview(background)
        self.view.addSubview(titleImg)
        let bp = ButtonPositions(controller: self)
        let play = button(bp.playY, named: "playButton.png")
        let leader = button(bp.leaderY, named: "leaderButton.png")
        let rate = button(bp.rateY, named: "rateButton.png")
        play.addTarget(self, action: "playPressed", forControlEvents: UIControlEvents.TouchDown)
        leader.addTarget(self, action: "leaderPressed", forControlEvents: UIControlEvents.TouchDown)
        rate.addTarget(self, action: "ratePressed", forControlEvents: UIControlEvents.TouchDown)
        self.view.addSubview(rate)
        self.view.addSubview(leader)
        self.view.addSubview(play)
     }

    func button(y:CGFloat, named name:String!) -> UIButton {
        let bp = ButtonPositions(controller: self)
        let img = UIImage(named: name)
        let b = UIButton(frame: CGRectMake(bp.x, y, self.view.frame.width / 1.5, img.size.height))
        b.setImage(img, forState: UIControlState.Normal)
        return b
    }

    func playPressed() {
        println("playPressed") //only prints once
       changeVC()
    }

    func changeVC() {
        self.presentViewController(GameViewController(), animated: true, completion: nil) //maybe initializing the GameViewController twice for some reason?
    }

    func leaderPressed() {

    }

    func ratePressed() {

    }

    func center() -> CGPoint {
        return CGPoint(x: CGRectGetMidX(self.view.frame), y: CGRectGetMidY(self.view.frame))
    }

    override func prefersStatusBarHidden() -> Bool {
        return true
    }
}


class GameViewController: UIViewController {
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        //prepareGame() 
        println("test") //this prints twice, even through the button press event is only triggered once
    }

    func prepareGame() {
            let skView = self.view as SKView //crashes here when called
            let scene = GameScene(size: self.view.bounds.size)
            skView.showsFPS = true
            skView.showsNodeCount = true
            skView.ignoresSiblingOrder = true
            scene.scaleMode = .AspectFill
            skView.presentScene(scene)

    }

    override func shouldAutorotate() -> Bool {
       return true
    }

    override func supportedInterfaceOrientations() -> Int {
        if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
            return Int(UIInterfaceOrientationMask.AllButUpsideDown.toRaw())
        } else {
            return Int(UIInterfaceOrientationMask.All.toRaw())
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    override func prefersStatusBarHidden() -> Bool {
        return false
    }
}

【问题讨论】:

  • 按定义转换不能失败。但是,您可以转换为错误的类型,这很可能是这里发生的事情。如果您有一个 UIView 并将其转换为 SKView 它不会从中生成一个 SKView,如果您尝试访问 UIView 没有的任何 SKView 属性/方法,它将崩溃。检查 self.view 是否真的是一个 SKView 实例。一个常见的原因是启用 iAd,它出于某种原因将视图控制器的视图替换为它自己的视图。
  • 崩溃报告显示堆栈跟踪而不是汇编代码。您所看到的是 Xcode 向您显示崩溃线程的顶部堆栈帧的汇编代码。您应该提供一个完全符号化的崩溃报告(例如,通过在没有调试器的情况下运行应用程序),否则您可能会得到猜测或假设,但仅此而已。
  • 哦,好的。谢谢你。我不应该说崩溃报告。当我在没有调试器的情况下运行时,按钮只是冻结在向下位置。当我尝试让 skView = self.view as 时? SKView 和打印出来的,skView 是 nil...

标签: ios xcode swift uikit sprite-kit


【解决方案1】:

我遇到了同样的问题。我使用适用于 iOS 的默认 Swift Game 项目创建了我的项目,该项目默认为 SceneKit 创建项目,因为我想使用 SpriteKit 并尝试将我的新场景投射到 SKView,如果我尝试投射,它会在线路上产生 EXC_BAD_ACCESS。为了解决我的问题,我不得不将主故事板中的 Class 更改为 SKView,因为它默认为 SCNView。

我遵循的修复步骤:

  1. 选择主故事板(在我的例子中是 Main.storyboard)
  2. 从 View Controller 下的层次结构中选择视图
  3. 选择身份检查器选项卡(右侧的实用程序面板)
  4. 在自定义类部分下,将类从 SCNView 更改为 SKView

这样做之后,问题就消失了。

【讨论】:

  • 奇怪的是,当我去检查视图在视图控制器中的哪个类时,它是 SKView... 我只好实例化一个全新的 SKView 并将其作为子视图添加到视图控制器的界面视图。感谢您的帮助!
【解决方案2】:

这不是最佳方式,但临时解决方法是创建一个新的 SKView 并将其添加到视图控制器的视图中。我试图避免这种情况,因为在场景开始时 fps 大约是 40,我看不出为什么它不应该是 60 当屏幕上什么都没有时。

编辑:添加一个计数器,因为该方法被调用两次也有助于 fps

private var count = 0
private func prepareGame() {
    count++
    if count == 2 {
        let skView = SKView(frame: self.view.frame)
        self.view.addSubview(skView)
        let scene = GameScene(size: skView.bounds.size)
        skView.showsFPS = true
        skView.showsNodeCount = true
        skView.ignoresSiblingOrder = true
        scene.scaleMode = .AspectFill
        skView.presentScene(scene)
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    • 1970-01-01
    • 2011-07-10
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多