I need to import 3D model from server URL but it's not working properly. Here is my code:
guard let path = modelPath, !path.isEmpty else {
fatalError("Failed to find model file path.")
}
guard let modelURL = URL(string: path) else {
fatalError("Failed to find model URL.")
}
let asset = MDLAsset(url:modelURL)
guard let object = asset.object(at: 0) as? MDLMesh else {
fatalError("Failed to get mesh from asset.")
}
...crash here at object
.
MDLAsset(url:)
does not handle downloading models from a server, it's only for URL
s that point to local storage.
You will have to download it yourself (using URLSession
or a framework like Alamofire).
Example using URLSession
:
Download task will return temporary location for the file that will be deleted after the callback closure return so if you need to reuse the file you will have to re-save it somewhere.
The tempLocation
file will have an extension of .tmp
, which MDLAsset
will not be able to process. Even if you don't need to persist the file, I didn't come up with a better way than to re-save it with the needed extension (.obj
that is).
let fileManager = FileManager.default
let localModelName = "model.obj"
let serverModelURL = URL(...)
let localModelURL = fileManager
.urls(for: .documentDirectory, in: .userDomainMask[0]
.appendingPathComponent(localModelName)
let session = URLSession(configuration: .default)
let task = session.downloadTask(with: modelURL) { tempLocation, response, error in
guard let tempLocation = tempLocation else {
// handle error
return
}
do {
// FileManager's copyItem throws an error if the file exist
// so we check and remove previously downloaded file
// That's just for testing purposes, you probably wouldn't want to download
// the same model multiple times instead of just persisting it
if fileManager.fileExists(atPath: localModelURL.path) {
try fileManager.removeItem(at: localModelURL)
}
try fileManager.copyItem(at: tempLocation, to: localModelURL)
} catch {
// handle error
}
let asset = MDLAsset(url: localURL)
guard let object = asset.object(at: 0) as? MDLMesh else {
fatalError("Failed to get mesh from asset.")
}
}
task.resume() // don't forget to call resume to start downloading