swiftmetalkitmodelio

Is ModelIO/MDLAsset myopic?


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/Resources 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).


Solution

  • 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.