是否可以将从运行时服务器恢复的图像加载到平面对象中?

时间:2018-02-08 15:15:38

标签: swift arkit

我被要求构建一个显示AR目录的应用程序,所以我需要做的很简单:当用户选择产品时,我必须将从base64恢复的图像从服务器加载到一个平面对象中。这是否可以使用swift-arkit?或者是否需要先将所有精灵/图像/纹理加载到资源文件夹中?

1 个答案:

答案 0 :(得分:0)

您绝对可以从服务器下载资源,将它们保存到设备(例如NSDocumentsDirectory),然后使用文件URL加载。我为你的类似用例做了 - 至少它听起来如此,根据你给出的描述 -

修改 这是相关的代码。我使用Alamofire从服务器下载ZIPFoundation进行解压缩。我相信如果你只是需要下载一个图像,它会更简单,可能不需要解压缩部分。

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

func loadNodeWithID(_ id: String, completion: @escaping (SCNNode?) -> Void) {
    // Check that assets for that model are not already downloaded
    let fileManager = FileManager.default
    let dirForModel = modelsDirectory.appendingPathComponent(id)
    let dirExists = fileManager.fileExists(atPath: dirForModel.path)
    if dirExists {
        completion(loadNodeWithIdFromDisk(id))
    } else {
        let dumbURL = "http://yourserver/yourfile.zip"
        downloadZip(from: dumbURL, at: id) {
            if let url = $0 {
                print("Downloaded and unzipped at: \(url.absoluteString)")
                completion(self.loadNodeWithIdFromDisk(id))
            } else {
                print("Something went wrong!")
                completion(nil)
            }
        }
    }
}

func loadNodeWithIdFromDisk(_ id: String) -> SCNNode? {
    let fileManager = FileManager.default
    let dirForModel = modelsDirectory.appendingPathComponent(id) 
    do {
        let files = try fileManager.contentsOfDirectory(atPath: dirForModel.path)
        if let objFile = files.first(where: { $0.hasSuffix(".obj") }) {
            let objScene = try? SCNScene(url: dirForModel.appendingPathComponent(objFile), options: nil)
            let objNode = objScene?.rootNode.firstChild()
            return objNode
        } else {
            print("No obj file in directory: \(dirForModel.path)")
            return nil
        }
    } catch {
        print("Could not enumarate files or load scene: \(error)")
        return nil
    }
}

func downloadZip(from urlString: String, at destFileName: String, completion: ((URL?) -> Void)?) {
    print("Downloading \(urlString)")
    let fullDestName = destFileName + ".zip"

    let destination: DownloadRequest.DownloadFileDestination = { _, _ in
        let fileURL = modelsDirectory.appendingPathComponent(fullDestName)
        return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
    }

    Alamofire.download(urlString, to: destination).response { response in
        let error = response.error
        if error == nil {
            if let filePath = response.destinationURL?.path {
                let nStr = NSString(string: filePath)
                let id = NSString(string: nStr.lastPathComponent).deletingPathExtension
                print(response)
                print("file downloaded at: \(filePath)")
                let fileManager = FileManager()
                let sourceURL = URL(fileURLWithPath: filePath)
                var destinationURL = modelsDirectory
                destinationURL.appendPathComponent(id)
                do {
                    try fileManager.createDirectory(at: destinationURL, withIntermediateDirectories: true, attributes: nil)
                    try fileManager.unzipItem(at: sourceURL, to: destinationURL)
                    completion?(destinationURL)
                } catch {
                    completion?(nil)
                    print("Extraction of ZIP archive failed with error: \(error)")
                }
            } else {
                completion?(nil)
                print("File path not found")
            }
        } else {
            // Handle error
            completion?(nil)
        }
    }
}