【问题标题】:Simulator working but device crashing when presenting UiViewController again模拟器工作但再次呈现 UiViewController 时设备崩溃
【发布时间】:2016-12-29 01:36:01
【问题描述】:

我一直在开发一款具有不同级别的游戏,您可以通过菜单进行访问。关卡是 3D 并使用 SceneKit,菜单是 2D 并使用 SpriteKit。

游戏从第 1 关开始,它是一个 UiViewController,当你击败它时,会出现菜单。如果您按下菜单中的按钮(显示“1 级”),您将被引导回到 1 级,但由于某种原因,在 iPhone 上再次加载 1 级时,它会崩溃,但模拟器工作正常。

我在这里有一个简单的示例代码,它的作用几乎相同,并且只在设备上崩溃:

import UIKit
import QuartzCore
import SceneKit

class GameViewController: UIViewController {


func ajrj() {
presentViewController(GameViewController(), animated: true, completion: nil)
}


override func viewDidLoad() {
    super.viewDidLoad()
    self.view = SCNView()
    var jarrarar = NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: #selector(GameViewController.ajrj), userInfo: nil, repeats: true)
    // create a new scene
    let scene = SCNScene(named: "art.scnassets/ship.scn")!

    // create and add a camera to the scene
    let cameraNode = SCNNode()
    cameraNode.camera = SCNCamera()
    scene.rootNode.addChildNode(cameraNode)

    // place the camera
    cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

    // create and add a light to the scene
    let lightNode = SCNNode()
    lightNode.light = SCNLight()
    lightNode.light!.type = SCNLightTypeOmni
    lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
    scene.rootNode.addChildNode(lightNode)

    // create and add an ambient light to the scene
    let ambientLightNode = SCNNode()
    ambientLightNode.light = SCNLight()
    ambientLightNode.light!.type = SCNLightTypeAmbient
    ambientLightNode.light!.color = UIColor.darkGrayColor()
    scene.rootNode.addChildNode(ambientLightNode)

    // retrieve the ship node
    let ship = scene.rootNode.childNodeWithName("ship", recursively: true)!

    // animate the 3d object
    ship.runAction(SCNAction.repeatActionForever(SCNAction.rotateByX(0, y: 2, z: 0, duration: 1)))

    // retrieve the SCNView
    let scnView = self.view as! SCNView

    // set the scene to the view
    scnView.scene = scene

    // allows the user to manipulate the camera
    scnView.allowsCameraControl = true

    // show statistics such as fps and timing information
    scnView.showsStatistics = true

    // configure the view
    scnView.backgroundColor = UIColor.blackColor()

    // add a tap gesture recognizer
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
    scnView.addGestureRecognizer(tapGesture)
}

func handleTap(gestureRecognize: UIGestureRecognizer) {
    // retrieve the SCNView
    let scnView = self.view as! SCNView

    // check what nodes are tapped
    let p = gestureRecognize.locationInView(scnView)
    let hitResults = scnView.hitTest(p, options: nil)
    // check that we clicked on at least one object
    if hitResults.count > 0 {
        // retrieved the first clicked object
        let result: AnyObject! = hitResults[0]

        // get its material
        let material = result.node!.geometry!.firstMaterial!

        // highlight it
        SCNTransaction.begin()
        SCNTransaction.setAnimationDuration(0.5)

        // on completion - unhighlight
        SCNTransaction.setCompletionBlock {
            SCNTransaction.begin()
            SCNTransaction.setAnimationDuration(0.5)

            material.emission.contents = UIColor.blackColor()

            SCNTransaction.commit()
        }

        material.emission.contents = UIColor.redColor()

        SCNTransaction.commit()
    }
}

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

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

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

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Release any cached data, images, etc that aren't in use.
}

}

这是一个错误吗?我应该相信模拟器吗?这是呈现视图控制器的坏方法吗?为什么会在设备上崩溃?

【问题讨论】:

  • 模拟器和设备是否运行相同版本的IOS?您应该检查设备日志并查看错误是什么。

标签: swift scenekit


【解决方案1】:

UIViewController 没有没有参数的初始化器。你应该使用这个:

public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)

并为其提供 xib 文件的名称。 模拟器可以处理这种情况 - 它会猜测 xib,但设备不会。

【讨论】:

  • 我把它放在 UIViewController 中了吗?以及如何为它提供 xib 文件的名称?什么是 xib 文件(可能是故事板,但我从不使用故事板)?
  • Xib 不是故事板的东西 - 它是您的视图控制器的 IB 文件。使用此初始化程序而不是“GameViewController()”。暗恋信息是什么?
  • 它给出了线程 10:信号 SGABRT,控制台显示:断言失败:(renderSize.x != 0),函数 -[SCNRenderContextMetal _setupDescriptor:forPass:isFinalTechnique:],文件 /BuildRoot/ Library/Caches/com.apple.xbs/Sources/SceneKit/SceneKit-332.6/sources/Core3DRuntime/NewRenderer/SCNRenderContextMetal.mm,第 688 行。
  • 这意味着您的 SCNView 的帧不正确(空宽度和/或高度)并且没有像素可以渲染。
  • @mnuages 我将 scnView.frame 的宽度和高度设置为 1 像素,并且它没有崩溃!但是在展示了几次场景之后,它开始滞后很多,然后崩溃并发出内存警告。有没有更好的方法来多次呈现 UIViewController?
【解决方案2】:

这对我来说就像是内存泄漏,因为随着程序运行它会逐渐变慢。看起来您每次呈现场景/视图时都会对其进行实例化。

计时器有一个对场景的字符串引用。它似乎在以前的 VC 上触发了 presentViewController()。每次通过(每 2 秒?为什么?)你会消耗另一个 VC 和场景。

我看不到堆栈从哪里弹出。

泄漏仪器显示什么?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    相关资源
    最近更新 更多