我有一点问题,下载后我想启动一个功能,但我有这个致命的错误:
致命错误:在解包可选值时意外发现nil
当我的下载结束时,我称之为功能telechargementOK()
func telechargementOK() {
println("Telechargement ok")
renduScene()
}
func renduScene() {
println("Chargement de la vue 3D")
let scnView2 = self.view3D as SCNView
scnView2.scene = SCNScene(named: "art.scnassets/MASTER.dae")
scnView2.autoenablesDefaultLighting = true
scnView2.allowsCameraControl = true
let filemgr = NSFileManager.defaultManager()
var documentsDirectoryURL = filemgr.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false, error: nil)
documentsDirectoryURL = documentsDirectoryURL?.URLByAppendingPathComponent("/Modules.scnassets/Module-01.dae")
let module1Scene = SCNScene(URL: documentsDirectoryURL!, options: nil, error: nil)
//println("\(module1Scene)")
scnViewModule1.scene = module1Scene
module1 = scnViewModule1.scene?.rootNode.childNodeWithName("Module-01", recursively: true)
//println("\(module1)")
scnView2.scene?.rootNode.addChildNode(module1!)
tapRecognizer.numberOfTapsRequired = 1
tapRecognizer.numberOfTouchesRequired = 1
tapRecognizer.addTarget(self, action: "sceneTapped:")
scnView2.addGestureRecognizer(tapRecognizer)
}
当我将此代码用于viewDidLoad()时,一切正常......
Stoun
更新:
这是我的完整代码:
//
// ViewController.swift
// Gare et Connexions
//
// Created by Stoun on 25/02/2016.
// Copyright (c) 2016 Stoun. All rights reserved.
//
import UIKit
import SceneKit
import Foundation
class ViewController: UIViewController {
@IBOutlet weak var view3D : UIView?
let tapRecognizer = UITapGestureRecognizer()
var scnView3 = SCNView()
var scnViewModule1 = SCNView()
var module1 = SCNNode?()
var connexion = NSString()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//1 - on va regarder pour copier les modules dans un dossier du dossier documents de l'appli
let filemgr = NSFileManager.defaultManager()
var error : NSError?
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
//test dossier
// path to documents directory
let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
// create the custom folder path
let myCustomDataDirectoryPath = documentDirectoryPath.stringByAppendingPathComponent("/Modules.scnassets")
// check if directory does not exist
if NSFileManager.defaultManager().fileExistsAtPath(myCustomDataDirectoryPath) == false {
// create the directory
var createDirectoryError: NSError? = nil
NSFileManager.defaultManager().createDirectoryAtPath(myCustomDataDirectoryPath, withIntermediateDirectories: false, attributes: nil, error: &createDirectoryError)
// handle the error, you may call an exception
if createDirectoryError != nil {
println("Handle directory creation error...")
}
}
//2-on teste la connexion
let status = Reach.connectionStatus()
switch status {
case .Unknown, .Offline:
println("Not connected")
connexion = "NON"
case .Online(.WWAN):
println("Connected via WWAN")
connexion = "3G"
case .Online(.WiFi):
println("Connected via WiFi")
connexion = "WIFI"
}
//3 - on télécharge ou pas
if ((connexion == "NON") || (connexion == "3G")){
//on telecharge pas, on mets une alerte pour dire que les modules ne sont peut-être pas à jour
// create the alert
let alert = UIAlertController(title: "MESSAGE IMPORTANT", message: "Vous n'êtes pas connecté à internet ou vous avez une connexion en 3G. Les modules ne sont peut-être pas à jour. Merci de vous connecter via un réseau wifi pour mettre à jour les modules.", preferredStyle: UIAlertControllerStyle.Alert)
// add an action (button)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
// show the alert
dispatch_async(dispatch_get_main_queue(), {
self.presentViewController(alert, animated: true, completion: nil)
})
renduScene()
}
else if (connexion == "WIFI"){
//on télécharge
var URL = NSURL(string: "http://urbis-guadeloupe.fr/stoun/3Dgare/Module-01-opt.dae.zip")
//var URL = NSURL(string: "http://urbis-guadeloupe.fr/stoun/3Dgare/B00001.png")
Downloader.load(URL!)
//renduScene()
scnView3 = self.view3D as SCNView
//on vois pour la suite - afficher la 3D
//let scnView = self.view3D as SCNView
scnView3.scene = SCNScene(named: "art.scnassets/MASTER.dae")
scnView3.autoenablesDefaultLighting = true
scnView3.allowsCameraControl = true
//scnViewModule1 = self.view3D as SCNView
//test chargement dossier document
/*if ((connexion == "NON") || (connexion == "3G")){
var documentsDirectoryURL = filemgr.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false, error: nil)
documentsDirectoryURL = documentsDirectoryURL?.URLByAppendingPathComponent("/Modules.scnassets/Module-01-opt.dae")
let module1Scene = SCNScene(URL: documentsDirectoryURL!, options: nil, error: nil)
//println("\(module1Scene)")
scnViewModule1.scene = module1Scene
module1 = scnViewModule1.scene?.rootNode.childNodeWithName("Module-01", recursively: true)
//println("\(module1)")
scnView3.scene?.rootNode.addChildNode(module1!)
/*let module1Scene = SCNScene(named: "art.scnassets/Module-01.dae")
scnViewModule1.scene = module1Scene
module1 = scnViewModule1.scene?.rootNode.childNodeWithName("Module-01", recursively: true)
scnView.scene?.rootNode.addChildNode(module1!)*/
}*/
tapRecognizer.numberOfTapsRequired = 1
tapRecognizer.numberOfTouchesRequired = 1
tapRecognizer.addTarget(self, action: "sceneTapped:")
scnView3.addGestureRecognizer(tapRecognizer)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func sceneTapped(recognizer: UITapGestureRecognizer) {
let scnView = self.view3D as SCNView
let location = recognizer.locationInView(scnView)
let hitResults = scnView.hitTest(location, options: nil)
if hitResults?.count > 0 {
let result = hitResults![0] as SCNHitTestResult
let node = result.node
println("Node select : \(result.node.name)")
if (result.node.name == "Module-01"){
println("Module-01")
}
}
}
func telechargementOK(){
println("Telechargement ok")
renduScene()
}
func renduScene() {
println("Chargement de la vue 3D")
if let scnView2 = self.view3D as? SCNView{
println(1)
scnView2.scene = SCNScene(named: "art.scnassets/MASTER.dae")
scnView2.autoenablesDefaultLighting = true
scnView2.allowsCameraControl = true
let filemgr = NSFileManager.defaultManager()
var documentsDirectoryURL = filemgr.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false, error: nil)
documentsDirectoryURL = documentsDirectoryURL?.URLByAppendingPathComponent("/Modules.scnassets/Module-01-opt.dae")
let module1Scene = SCNScene(URL: documentsDirectoryURL!, options: nil, error: nil)
println("\(module1Scene)")
scnViewModule1.scene = module1Scene
module1 = scnViewModule1.scene?.rootNode.childNodeWithName("Module-01", recursively: true)
println("\(module1)")
scnView2.scene?.rootNode.addChildNode(module1!)
tapRecognizer.numberOfTapsRequired = 1
tapRecognizer.numberOfTouchesRequired = 1
tapRecognizer.addTarget(self, action: "sceneTapped:")
scnView2.addGestureRecognizer(tapRecognizer)
}
else {
println(2)
let filemgr = NSFileManager.defaultManager()
var documentsDirectoryURL = filemgr.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false, error: nil)
documentsDirectoryURL = documentsDirectoryURL?.URLByAppendingPathComponent("/Modules.scnassets/Module-01-opt.dae")
let module1Scene = SCNScene(URL: documentsDirectoryURL!, options: nil, error: nil)
println("\(module1Scene)")
scnViewModule1.scene = module1Scene
module1 = scnViewModule1.scene?.rootNode.childNodeWithName("Module-01", recursively: true)
println("\(module1)")
scnView3.scene?.rootNode.addChildNode(module1!)
}
}
}
当设备连接到互联网时,这是日志:
Connected via WiFi
Success: 200
Copy from serveur successful
Remove ZIP successful
Remove dae from folder successful
Copy dae in folder successful
Remove dae from folder successful
Telechargement ok
Chargement de la vue 3D
2
Optional(<SCNScene: 0x1780e1c80>)
Optional(<SCNNode: 0x100b11a20 'Module-01' | 4 children>)
但SCNNode Module-01不在视图
上当设备离线时,日志:
Not connected
Chargement de la vue 3D
1
Optional(<SCNScene: 0x1780f7c80>)
Optional(<SCNNode: 0x13fe271b0 'Module-01' | 4 children>)
一切都在观点上 我不明白为什么当设备在线时,节点不在视图上!
Stoun
答案 0 :(得分:0)
你使用module1!
而不检查module1是不是nil:你应该检查它。
答案 1 :(得分:0)
您正在从SCNView和其他顶级对象(scnViewModule1
和scnView2
)开始查找子节点,这些对象在viewDidLoad()之前不存在。因此,您的搜索返回nil,并且您的力展开失败。如果从viewDidLoad()调用方法,则场景已经实例化,因此您的调用成功。
您无需通过视图来操纵场景。相反,尝试
scnViewModule1.scene = module1Scene
if let module1 = module1Scene.rootNode.childNodeWithName("Module-01", recursively: true) {
module1Scene.rootNode.addChildNode(module1)
}