使用场景工具包和swift IOS调用func时出现致命错误

使用场景工具包和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

我有一个小问题,下载后我想启动一个函数,但我有一个致命错误:

致命错误:在展开可选值时意外发现nil

下载结束后,我调用函数telechargementOK()

当我把这段代码带到viewDidLoad()时,一切都正常

斯托恩

更新:

这是我的完整代码:

//
//  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,如果可以,我将调用我的函数。