Strange behaviour of iOS browser on iOS 9.3.5


#1

Hi, if you attempt to provide a filter that isn’t matched then the following dialog is presented suggesting that some settings need to be changed rather than the fact that the filter has not been matched. This stops the users drilling down into folders to find files of the specified type.

This can be easily reproduced by changing the juce demo app to use the following:

else if (type >= loadChooser && type <= saveChooser)
    {
        const bool useNativeVersion = nativeButton.getToggleState();

        if (type == loadChooser)
        {
            fc = new FileChooser ("Choose a file to open...",
                                  File::getCurrentWorkingDirectory(),
                                  "*.xyz",
                                  useNativeVersion);

Edit: Also noticed that not all filters are matching correctly. In the next screenshot, the filter has been passed in as “.prs;.xml” yet only the .xml files are selectable:

If I change the filter to “*” then the .abc and .xml files are selectable, but still not the .prs. The only correlation I can see here is that the .abc and .xml are text files, and the .prs is a binary file.


#2

The lack of exact matching between filters and available files is because Apple introduced Uniform Type Identifiers to describe file types and a particular filter may result in a UTI that subsequently supports multiple file extensions. Each filter passed is converted internally to a UTI. The strange dialog occurs because Apple does not recognise *.xyz" extension and cannot generate a well known UTI for it. Apparently when only such dynamic UTIs are passed to file chooser, we get this unhelpful dialog from Apple. If at least one of the filters is recognised, then the file chooser works fine. I wish Apple provided a more useful dialog.

I am not sure what we can do on JUCE end at this point. We could for instance go through the list of all documented UTIs https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html#//apple_ref/doc/uid/TP40009259-SW1 and add each to a known list in JUCE, firing an assert if a dynamic type is returned but such lists quickly get out of date and we would have to continuously update it in code. The public.alembic UTI (which is UTI for your *.abc) is not defined there for instance. Even if we checked if UTI array contained only UTIs starting with dyn prefix, that does not feel to be a particularly robust and persistent solution.

As for your issue with matching prs and xml at once, have you tried *.prs;*.xml ? I have tried multiple file extensions and they worked fine on my end, i.e. when adding * to the filter for each extension.


#3

Thanks for the info, all good stuff to know. Yes, when I was talking about the .prs and .xml I should have put the * on on this message, but they’re on all the extensions in the code. So *.abc; *.xml picks up the files. *.prs; *.xml doesn’t pick up the prs file. * picks up the *.abc files but not the *.prs file. As mentioned, the only difference between the .abc file I have is that it’s actually just a renamed .xml file, whereas the .prs file is a binary sysex file.

Edit: just checked .prs;.xml on iOS 11 and that doesn’t work either, I’m guessing as there is no UTI defined for .prs? (I can’t see where the .abc is on that list either).


#4

Yes, there is not a know UTI for *.prs extension.

To be able to support custom extensions, each app needs to declare its own UTIs. Then you will be able to pick *.prs documents for instance. Bear in mind that public UTIs take precedence, so when creating a new UTI one must check with public UTI reference. It is not completely up to date as we know, but that’s still better than nothing.

To support this, I will update Projucer to allow specifying custom UTIs for one’s app. You will need to register your *.prs extension there.


#5

Ok, on a second thought, because one can specify multiple file extensions per app, it will be faster and simpler to specify a custom plist section in Projucer. Below an example for the *.prs file:

<plist>
  <dict>
    <key>UTExportedTypeDeclarations</key>
    <array>
        <dict>
            <key>UTTypeIdentifier</key>
            // Required: This should be a unique identifier within a system, so it is best to use
            // a reverse domain name with your bundle ID
            <string>com.mycompany.document.prs</string>
            <key>UTTypeReferenceURL</key>
            // Optional: URL to document describing the format
            <string>http://www.mycompany.com/prs_info.html</string>
            <key>UTTypeDescription</key>
            // User friendly description of the format
            <string>PRS document</string>
            <key>UTTypeIconFile</key>
            // Optional: an icon for the extension
            <string>Icons.icns</string>
            <key>UTTypeConformsTo</key>
            <array>
                // Optional: Specifies to which file filter this file type conforms, so
                // if public.data is specified, then it will conform to "*"
                <string>public.data</string>
            </array>
            <key>UTTypeTagSpecification</key>
            <dict>
                <key>public.filename-extension</key>
                <array>
                    // Required
                    <string>prs</string>
                </array>
                <key>public.mime-type</key>
                // Optional (I just picked something here as an example)
                <string>application/octet-stream</string>
            </dict>
        </dict>
        </dict>
            // other custom formats go here
        </dict>
    </array>
  </dict>
</plist>

Just remove the comments I added and you will be good to go. The “conforms to” section usually can be just public.data for most of the cases. If you declare a new image file type for instance, then you could add another entry on top of public.data as <string>public.image</string>


#6

perfect, thanks