matt
matt

Reputation: 535944

iOS 13 thumbnail extension (QLThumbnailProvider) not being called

My document browser-based test app is working fine. It shows the browser. It has a special exported document type. I can create files of that type, I can open files of that type.

There's just one problem. My app also includes a Thumbnail Extension. As far as I can tell, that extension's single method (the override of QLThumbnailProvider provideThumbnail(for:_:)) is never being called. So my files, as shown in the document browser, the Files app, etc., do not have the correct thumbnail.

Has anyone gotten thumbnail extensions to work in iOS 13? I'm testing on a device (because document browser apps don't work on the simulator).

Here are my Info.plist settings. First, the app. Here's the part where we define the document type and export the UTI:

<key>CFBundleDocumentTypes</key>
<array>
    <dict>
        <key>CFBundleTypeIconFiles</key>
        <array/>
        <key>CFBundleTypeName</key>
        <string>PeopleGroup2</string>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>LSHandlerRank</key>
        <string>Owner</string>
        <key>LSItemContentTypes</key>
        <array>
            <string>com.neuburg.pplgrp2new</string>
        </array>
    </dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
    <dict>
        <key>UTTypeConformsTo</key>
        <array>
            <string>public.content</string>
            <string>public.data</string>
        </array>
        <key>UTTypeDescription</key>
        <string>PeopleGroup2</string>
        <key>UTTypeIconFiles</key>
        <array/>
        <key>UTTypeIdentifier</key>
        <string>com.neuburg.pplgrp2new</string>
        <key>UTTypeTagSpecification</key>
        <dict>
            <key>public.filename-extension</key>
            <string>pplgrp2new</string>
        </dict>
    </dict>
</array>

And here's the key part of the Thumbnail Extension Info.plist:

<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>QLSupportedContentTypes</key>
        <array>
            <string>com.neuburg.pplgrp2new</string>
        </array>
        <key>QLThumbnailMinimumDimension</key>
        <integer>10</integer>
    </dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.quicklook.thumbnail</string>
    <key>NSExtensionPrincipalClass</key>
    <string>$(PRODUCT_MODULE_NAME).ThumbnailProvider</string>
</dict>

As you can see, the thumbnail extension supported content type matches the app's exported UTI. But the ThumbnailProvider code is apparently not being called.

Here's the thumbnail provider code, just a rock-bottom test:

@objc class ThumbnailProvider: QLThumbnailProvider {
    override func provideThumbnail(for request: QLFileThumbnailRequest, 
        _ handler: @escaping (QLThumbnailReply?, Error?) -> Void) {
            let url = Bundle.main.url(forResource: "smiley", withExtension: "jpg")!
            let reply = QLThumbnailReply(imageFileURL: url)
            handler(reply, nil)
    }
}

But it doesn't seem to be called.

Could someone show me an example that actually works?

The actual test project is here:

https://github.com/mattneub/Programming-iOS-Book-Examples/tree/master/bk2ch23p810DocumentBrowser

EDIT: The release of iOS 13.2 has not magically made this start working.

Upvotes: 5

Views: 2016

Answers (3)

entonio
entonio

Reputation: 2173

I'm not sure this solves the OP's problem, but it just might. Apparently, 9 out of 10 people who try implementing a Thumbnail extension stumble upon its simply not being called, and I've found no help at all online, pssibly because those who solved the issue didn't notice what the solution was.

But after much hopeless trying, I got it to work by doing two things:

  1. I did find that you need to add an Entitlements file to the root of your extension, just like you have for the host app, e.g.

YourExtensionName.entitlements

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.files.user-selected.read-only</key>
    <true/>
</dict>
</plist>

Apple mentions this nowhere in the Thumbnails documentation, nor is it created by Xcode's template.

  1. ALSO, the file type identifier should be tld.yourdomain.yourextension, all lowercase. I'm not saying other things don't work, but I could only make it work with this format.

This has solved the problem for me. The extension gets called whenever I use SwiftUI's fileImporter, fileExporter, or the Files app.

To debug the extension, run its own target, Xcode will ask what app to use for it, tell it to use the host app. Breakpoints will work, as will print, NSLog, Logger(), and os_log.

Upvotes: 0

Torront&#233;s
Torront&#233;s

Reputation: 197

I know the question is very old, and I apologize in advance if my suggestion is too obvious, but have you checked that smiley.jpg has the correct target membership? It should a member of the thumbnail extension target. I haven't tried this with your example, but in my own setting, I found that if the membership is set, for example, to the main app and not to the extension, your problem crops up. Hope this helps. By the way, I wasted an inordinate amount of time trying to make QLThumbnailProvider work with QLThumbnailReply(contextSize:currentContextDrawing:), to no avail. What a PITA. The other initializers worked OK.

Upvotes: 0

libe
libe

Reputation: 11

Since iOS13, there a new QuickLookThumbnailing.framework that handles thumbnailing for iOS and macOS. Make sure that it is linked by your extension or you will get a silent crash when dyld will try to load the framework.

Upvotes: 1

Related Questions