使用场景工具包和swift IOS调用func时出现致命错误
我有一个小问题,下载后我想启动一个函数,但我有一个致命错误: 致命错误:在展开可选值时意外发现nil 下载结束后,我调用函数telechargementOK() 当我把这段代码带到viewDidLoad()时,一切都正常 斯托恩 更新: 这是我的完整代码:使用场景工具包和swift IOS调用func时出现致命错误,ios,swift,scenekit,Ios,Swift,Scenekit,我有一个小问题,下载后我想启动一个函数,但我有一个致命错误: 致命错误:在展开可选值时意外发现nil 下载结束后,我调用函数telechargementOK() 当我把这段代码带到viewDidLoad()时,一切都正常 斯托恩 更新: 这是我的完整代码: // // ViewController.swift // Gare et Connexions // // Created by Stoun on 25/02/2016. // Copyright (c) 2016 Stoun. A
//
// 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!)
}
}
}
当设备连接到internet时,这是日志:
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>)
Not connected
Chargement de la vue 3D
1
Optional(<SCNScene: 0x1780f7c80>)
Optional(<SCNNode: 0x13fe271b0 'Module-01' | 4 children>)
通过WiFi连接
成功:200
从服务器复制成功
成功删除压缩包
成功从文件夹中删除dae
成功复制文件夹中的dae
成功从文件夹中删除dae
远程充电正常
la vue 3D收费
2.
可选()
可选()
但SCNNode Module-01不在视图中
当设备脱机时,日志:
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>)
Not connected
Chargement de la vue 3D
1
Optional(<SCNScene: 0x1780f7c80>)
Optional(<SCNNode: 0x13fe271b0 'Module-01' | 4 children>)
未连接
la vue 3D收费
1.
可选()
可选()
一切都在眼前
我不明白为什么当设备在线时节点不在视图中
Stoun您使用
模块1代码>不检查module1是否为零:您应该检查它 您正在从SCNView和其他顶级对象(scnViewModule1
和scnView2
)开始查找子节点,这些对象在viewDidLoad()之前不存在。因此,搜索返回nil,强制展开失败。如果从viewDidLoad()调用方法,则场景已实例化,因此调用成功
您不需要仅通过视图来操纵场景。相反,试试看
scnViewModule1.scene = module1Scene
if let module1 = module1Scene.rootNode.childNodeWithName("Module-01", recursively: true) {
module1Scene.rootNode.addChildNode(module1)
}
下载任务可能是异步的,您使用了错误的位置(和时间!)继续。在调用telechargementOK()之前,下载的文件将写入documentDirectory,如果可以,我将调用我的函数。