A common way to load an ".obj
" using Swift/MDLAsset
uses code like
import ModelIO
var theURL: URL
var theAsset: MDLAsset
theURL = Bundle.main.url(forResource: "cube", withExtension: "obj")!
theAsset = MDLAsset(url: theURL)
This only works for files in the app's main bundle
(in app/Contents/Resource
s on macOS
).
But I would like my app to read files from anywhere on my filesystem. So I tried the following
// 1st attempt
theURL = URL(string: "file:///Users/me/cube.obj")!
theAsset = MDLAsset(url: theURL)
// 2nd attempt
theURL = URL(fileURLWithPath: "/Users/me/cube.obj")
theAsset = MDLAsset(url: theURL)
// 3rd attempt
theURL = URL(string: "cube.obj", relativeTo: URL(string:"/Users/me/")!)!
theAsset = MDLAsset(url: theURL)
They all failed (with error message "Could not open OBJ file"
). This only occurs when the "cube.obj"
file does not live under app/Contents/Resources
.
My naive conclusion is that MDLAsset
seems to be myopic -- it's only looking in one place: app/Contents/Resources.
I'm sure there must be a solution (other than always copying my obj files into the app's resources).
The problem is not specific to ModelIO or MDLAsset; it's a general problem with sandboxed apps. A sandboxed app doesn't have access to arbitrary user files, it can only access files in its own sandbox unless user interaction has granted it access to other files.
For example, if your app were to use a file-open dialog (NSOpenPanel
) to ask the user to select a model object file, and the user were to do so, then your app would gain access to that file.