(SOLVED) iOS ContentSharer::shareFiles() failing with valid URL

Hey everyone,

I have a problem using the ContentSharer class on iOS. I try to use this bit of code:

auto contentSharer = ContentSharer::getInstance();
jassert(tempFile.exists()); // class member of type File, just making sure it really exists

Array<URL> files;
contentSharer->shareFiles(files, [&](bool sucess, const String& error)

Unfortunately the call to shareFiles() fails. ContentSharer::shareFiles() itself makes a call to ContentSharer::share(NSArray*), and this share() function starts off with an assertion, checking if the NSArray is empty. This assertion triggers because, indeed, the Array delivered there by the shareFiles() function is empty.

I stepped through the shareFiles() function and found, that the URL I’m providing is hitting the following else statement on line 74 of juce_ios_ContentSharer.cpp:

if ([fileDirectory length] == NSUInteger (0))
                    nativeFilePath = [[NSBundle mainBundle] pathForResource: fileName
                                                                     ofType: fileExt];
                else ///<— function call makes it all the way here
                    nativeFilePath = [[NSBundle mainBundle] pathForResource: fileName
                                                                     ofType: fileExt
                                                                inDirectory: fileDirectory];

I checked, and all 3 variables (fileName, fileExt, fileDirectory) are valid. The line executes and the code continues, but after that line nativeFilePath is still nil.
This results in the array being handed to the share() function itself being empty. I have no idea why this would fail, given that fileName, fileExt and fileDirectory variables show the right content.
Do I have to do something differently in my original call? Is the Array I’m sending into the function setup correctly? Why could this fail? Before I call the function I check that the file exists with an assertion, I also used an iOS file explorer to go into the directory manually and there the file is. All debugging leads me to is that this shouldn’t fail but it does…

Also, the shareFile() function starts off by checking if the file I provide is a local file like so:

 if (f.isLocalFile())
                nativeFilePath = juceStringToNS (f.getLocalFile().getFullPathName());

f.isLocalFile() comes back false… the full pathname of f as being used all throughout the function is:

Any help would be appreciated :slight_smile:

Took a bit of digging, but it looks like the root of the problem is that shareFiles expects an array of URLs that are either fully qualified URLs to files on disk or relative URLs that will be looked up within the app bundle directory.

Array<URL> files;

This construction of the URL Array hits the URL constructor with a juce::String argument, which probably assumes that you’ve set your URL scheme in the string argument. In this case, you don’t have that, so when you go on to pass that array to the content sharer, it looks like a list of URLs that it should find in your bundle directory, hence why the isLocalFile() call comes back false.

If instead your array construction looks like

Array<URL> files {{ tempFile }};

Then you’ll hit the URL constructor with a juce::File argument, and in that case the constructor correctly prepends the file:// scheme, which then passes the isLocalFile() check and informs the content sharer that this is referring to a specific file on disc and not something to be found in the bundle directory lookup

I think that’s all you need!

1 Like

Awesome, this absolutely did the trick, no idea how that constructor for URL slipped past me. I’ve been up and down the docs all day yesterday… embarrassing :grimacing:

Thanks for taking the time to figure this out! I’ll mark the topic as solved