从 SCNScene url 获取下载进度 [英] Get download progress from SCNScene url

查看:28
本文介绍了从 SCNScene url 获取下载进度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 ARKit,但无法从 SCNScene url 获取下载进度.这是我的代码:

func downloadModel(hitTestResult: ARHitTestResult) {DispatchQueue.global().async {//创建加载视图//我想在这里获得下载进度let loading = UIAlertController(title: nil, message: "请稍候...\(downloadProgressValueHere)%", preferredStyle: .alert)让 loadingIndicator = UIActivityIndi​​catorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))loadingIndicator.hidesWhenStopped = trueloadingIndicator.activityIndi​​catorViewStyle = UIActivityIndi​​catorViewStyle.grayloadingIndicator.startAnimating();loading.view.addSubview(loadingIndicator)self.present(加载,动画:true,完成:nil)//从服务器下载 3d 模型让 myURL = URL(string: "http://www.mydownloadlink.com")让场景=尝试!SCNScene(url: myURL!, options: nil)让 node = (scene.rootNode.childNode(withName: "parentNode", recursively: true))!self.sceneView.scene.rootNode.addChildNode(node)//关闭加载视图loading.dismiss(动画:true,完成:nil)}}

如何获取请稍候..."消息的下载进度?谢谢大家.

解决方案

据我所知,虽然以下方法似乎会采用远程 URL,但实际上并非如此(尽管我可能是错的):

>

convenience init(url: URL,选项:[SCNSceneSource.LoadingOption : Any]?= nil) 抛出

无论如何,在这里回答你的问题是一个例子(可能有点OTT,但希望它也能帮助其他人).

假设我们有一个位于以下 URLSCNScene 文件:

http://stackOverflow.com/stackOverFlow.scn

首先我们需要为我们的 ProgressInfo 创建变量,如下所示:

 var loading: UIAlertController!var loadingIndicator: UIActivityIndi​​catorView!var downloadString: String = "下载"

然后我们要做的是创建一个 URLSession 来下载文件,如下所示:

///从远程 URL 下载 SCN 文件函数下载场景任务(){//1.获取 SCN 文件的 URL守卫让 url = URL(string: "http://stackOverflow.com/stackOverFlow.scn") else { return }//2.创建下载会话让 downloadSession = URLSession(配置:URLSession.shared.configuration,委托:self,delegateQueue:nil)//3.创建下载任务 &运行让 downloadTask = downloadSession.downloadTask(with: url)下载任务.resume()//4.显示进度警报DispatchQueue.main.async {self.loading = UIAlertController(title: nil, message: self.downloadString , preferredStyle: .alert)让 loadingIndicator = UIActivityIndi​​catorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))loadingIndicator.hidesWhenStopped = trueloadingIndicator.activityIndi​​catorViewStyle = UIActivityIndi​​catorViewStyle.grayloadingIndicator.startAnimating();self.loading.view.addSubview(loadingIndicator)self.present(self.loading,动画:true,完成:nil)}}

请注意,我创建了一个 variable 导致 downloadString 我们稍后更改.

然后我们将参考以下 URLSession 委托,例如:

class ViewController: UIViewController, URLSessionDelegate, URLSessionDownloadDelegate {}

对于我们的示例,将调用以下函数:

第一个跟踪我们下载进度的工具,您可以在其中处理诸如在 HUD 中显示进度或使用 progressIndicator 之类的事情:

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,didWriteData bytesWritten: Int64,写入的总字节数:Int64,totalBytesExpectedToWrite: Int64) {打印(下载\(totalBytesWritten)/的\(totalBytesExpectedToWrite)字节")DispatchQueue.main.async {self.loading.message = "已下载 \(totalBytesWritten)/Of \(totalBytesExpectedToWrite) 字节"}}

文件下载后处理的第二个:

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {//1.删除加载视图loading.dismiss(动画:true,完成:nil)//2.创建文件名让 fileURL = getDocumentsDirectory().appendingPathComponent("stackOverFlow.scn")//3.将其复制到文档目录做 {试试 FileManager.default.copyItem(at: location, to: fileURL)打印(成功保存文件\(fileURL)")//4.加载模型加载模型()} 抓住 {打印(错误保存:\(错误)")}}

请注意,在此方法中,我使用以下函数检索下载的文件并将其复制到 documents 目录:

////返回文档目录//////- 返回:URLfunc getDocumentsDirectory() ->网址{让路径 = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)让文档目录 = 路径 [0]返回文件目录}

一旦文件被下载并复制过来,我们就 (4) 像这样调用我们的 loadModel 函数:

////从文档目录加载 SCNFile功能加载模型(){//1.获取下载文件的路径让downloadedScenePath = getDocumentsDirectory().appendingPathComponent("stackOverFlow.scn")做 {//2.加载场景记住 Init 只需要一个本地 URL让 modelScene = 尝试 SCNScene(网址:downloadedScenePath,选项:nil)//3.创建一个节点来保存所有内容让 modelHolderNode = SCNNode()//4.从 SCNFile 中获取所有节点让 nodeArray = modelScene.rootNode.childNodes//5.将它们添加到持有者节点对于 nodeArray 中的 childNode {modelHolderNode.addChildNode(childNode 作为 SCNNode)}//6.设置位置modelHolderNode.position = SCNVector3(0, 0, -1.5)//7.将其添加到场景中self.augmentedRealityView?.scene.rootNode.addChildNode(modelHolderNode)} 抓住  {打印(错误加载场景")}}

请注意,这是一个非常粗略的示例,不包括检查文件是否存在、缩放等内容,但它应该足以帮助您实现所需的...

I'm working with ARKit, I have trouble getting download progress from SCNScene url. This is my code:

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)
    }
}

How can I get download progress to "Please wait..." message? Thanks all.

解决方案

It is my understanding that whilst it appears that the following method would take a remote URL in actuality it doesn't (although I could be wrong):

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

Anyway to answer your question here is an example for you (which is probably a bit OTT, but hopefully it will help others as well).

Lets say we an SCNScene file at the following URL:

http://stackOverflow.com/stackOverFlow.scn

Firstly we need to create variables for our ProgressInfo like so:

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

Then what we will do is create a URLSession to download the file like so:

 /// 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)
    }

 }

Note that I have create a variable caused downloadString which we change later.

We will then make reference to following URLSession Delegates e.g:

class ViewController: UIViewController, URLSessionDelegate, URLSessionDownloadDelegate {

}

Which for our example will call the following functions:

The 1st to track the progress of our download in which you can handle things like showing the progress in a HUD or using a 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"
    }

}

The 2nd to handle when the file has downloaded:

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)")
 }
}

Note that in this method I am making use of the following function to retrieve and copy the downloaded file to the 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

}

Once the file has been downloaded and copied across we then (4) call our loadModel function like so:

/// 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")
    }

}

Please note that this is a very crude example, and doesn't cover things like checking if the file exists, scaling etc, but it should be enough to help you achieve what you are looking for...

这篇关于从 SCNScene url 获取下载进度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆