Получите прогресс загрузки от SCNScene url - PullRequest
0 голосов
/ 25 апреля 2018

Я работаю с ARKit, у меня проблемы с получением прогресса загрузки по URL SCNScene.Это мой код:

func downloadModel(hitTestResult: ARHitTestResult) {
    DispatchQueue.global().async {
        // create loading view
        // I WANT TO GET DOWNLOAD PROGRESS HERE
        let loading = UIAlertController(title: nil, message: "Please wait...\(downloadProgressValueHere)%", preferredStyle: .alert)

        let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
        loadingIndicator.hidesWhenStopped = true
        loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
        loadingIndicator.startAnimating();

        loading.view.addSubview(loadingIndicator)
        self.present(loading, animated: true, completion: nil)

        // download 3d model from server
        let myURL = URL(string: "http://www.mydownloadlink.com")
        let scene = try! SCNScene(url: myURL!, options: nil)
        let node = (scene.rootNode.childNode(withName: "parentNode", recursively: true))!
        self.sceneView.scene.rootNode.addChildNode(node)

        // dismiss loading view
        loading.dismiss(animated: true, completion: nil)
    }
}

Как я могу получить информацию о прогрессе загрузки в сообщении «Пожалуйста, подождите ...»?Спасибо всем.

1 Ответ

0 голосов
/ 25 апреля 2018

Насколько я понимаю, хотя следующий метод в действительности использует удаленный URL, он этого не делает (хотя я могу ошибаться):

convenience init(url: URL, 
         options: [SCNSceneSource.LoadingOption : Any]? = nil) throws

В любом случае ответить на ваш вопрос здесьпример для вас (что, вероятно, немного OTT, но, надеюсь, это поможет и другим).

Допустим, мы SCNScene файл в следующем URL:

http://stackOverflow.com/stackOverFlow.scn

Во-первых, нам нужно создать переменные для нашего ProgressInfo примерно так:

 var loading: UIAlertController!
 var loadingIndicator: UIActivityIndicatorView!
 var downloadString: String = "Downloading"

Затем мы создадим URLSession для загрузки файла следующим образом:

 /// Downloads An SCNFile From A Remote URL
 func downloadSceneTask(){

        //1. Get The URL Of The SCN File
        guard let url = URL(string: "http://stackOverflow.com/stackOverFlow.scn") else { return }

        //2. Create The Download Session
        let downloadSession = URLSession(configuration: URLSession.shared.configuration, delegate: self, delegateQueue: nil)

        //3. Create The Download Task & Run It
        let downloadTask = downloadSession.downloadTask(with: url)
        downloadTask.resume()

        //4. Show The Progress Alert
        DispatchQueue.main.async {

           self.loading = UIAlertController(title: nil, message: self.downloadString , preferredStyle: .alert)

           let loadingIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
           loadingIndicator.hidesWhenStopped = true
           loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
           loadingIndicator.startAnimating();

           self.loading.view.addSubview(loadingIndicator)
           self.present(self.loading, animated: true, completion: nil)
    }

 }

Обратите внимание, что я создал variable вызванный downloadString, который мы изменим позже.

Затем мы сделаем ссылку на следующие делегаты URLSession, например:

class ViewController: UIViewController, URLSessionDelegate, URLSessionDownloadDelegate {

}

, которые для нашего примера вызовутследующие функции:

1-й для отслеживания прогресса нашей загрузки, в котором вы можете обрабатывать такие вещи, как отображение прогресса в HUD или с помощью progressIndicator:

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,
                    didWriteData bytesWritten: Int64,
                    totalBytesWritten: Int64,
                    totalBytesExpectedToWrite: Int64) {

        print("Downloaded \(totalBytesWritten) / Of \(totalBytesExpectedToWrite) Bytes")

        DispatchQueue.main.async {
           self.loading.message = "Downloaded \(totalBytesWritten) / Of \(totalBytesExpectedToWrite) Bytes"
    }

}

2-й для обработки, когда файл загружен:

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {

//1. Remove The Loading View
    loading.dismiss(animated: true, completion: nil)

//2. Create The Filename
let fileURL = getDocumentsDirectory().appendingPathComponent("stackOverFlow.scn")

//3. Copy It To The Documents Directory
do {
    try FileManager.default.copyItem(at: location, to: fileURL)

    print("Successfuly Saved File \(fileURL)")

    //4. Load The Model
    loadModel()

} catch {

    print("Error Saving: \(error)")
 }
}

Обратите внимание, что в этом методе я использую следующую функцию для извлечения и копирования загруженного файла в documents directory:

/// Returns The Documents Directory
///
/// - Returns: URL
func getDocumentsDirectory() -> URL {

let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory

}

После загрузки файла ископировав их, мы затем (4) называем наш loadModel function следующим образом:

/// Loads The SCNFile From The Documents Directory
func loadModel(){

    //1. Get The Path Of The Downloaded File
    let downloadedScenePath = getDocumentsDirectory().appendingPathComponent("stackOverFlow.scn")

    do {

        //2. Load The Scene Remembering The Init Takes ONLY A Local URL
        let modelScene =  try SCNScene(url: downloadedScenePath, options: nil)

        //3. Create A Node To Hold All The Content
        let modelHolderNode = SCNNode()

        //4. Get All The Nodes From The SCNFile
        let nodeArray = modelScene.rootNode.childNodes

        //5. Add Them To The Holder Node
        for childNode in nodeArray {
            modelHolderNode.addChildNode(childNode as SCNNode)
        }

        //6. Set The Position
        modelHolderNode.position = SCNVector3(0, 0, -1.5)

        //7. Add It To The Scene
        self.augmentedRealityView?.scene.rootNode.addChildNode(modelHolderNode)


    } catch  {
        print("Error Loading Scene")
    }

}

Обратите внимание, что это очень грубый пример, и он не охватывает такие вещи, как проверка существования файла, масштабирование и т. д.,но этого должно быть достаточно, чтобы помочь вам достичь того, что вы ищете ...

...