Reputation: 697
I'm developing a QLThumbnailProvider extension to display thumbnails for my document type. My extension does not appear to be being called - my thumbnails are not appearing and I'm not seeing the logging I've added appearing in any log files.
I have an UIDocumentBrowserViewController based app that defines a new document type. It exports an UTI (com.latenightsw.Eureka.form
). My app is able to browse, create and open documents, but the thumbnails are blank.
I've added a Thumbnail Extension target to my project. The code looks like this:
class ThumbnailProvider: QLThumbnailProvider {
override func provideThumbnail(for request: QLFileThumbnailRequest, _ handler: @escaping (QLThumbnailReply?, Error?) -> Void) {
// Third way: Set an image file URL.
print("provideThumbnail: \(request)")
handler(QLThumbnailReply(imageFileURL: Bundle.main.url(forResource: "EurekaForm", withExtension: "png")!), nil)
}
}
I've confirmed that EurekaForm.png
is part of the target and being copied to the extension's bundle (as well as the host app's bundle).
And I've confirmed that my UTI is declared:
Does anyone have any suggestions?
Upvotes: 4
Views: 2102
Reputation: 2482
In my case, the extension didn't work in the simulator (Xcode 11.1). Everything works as expected on a real device (iOS 13.1.2).
Upvotes: 0
Reputation: 13273
It appears that logging and breakpoints sometimes do not work inside app extension. Even fatalError
s occur silently.
In my project I could not get the initialiser QLThumbnailReply(imageFileURL:)
to work. However the other initialisers seem to work better.
When using the context initialiser you have to use a context size which lies between request.minimumSize
and request.maximumSize
.
Below I've written some code which takes an image and draws it into the context while keeping the above conditions.
override func provideThumbnail(for request: QLFileThumbnailRequest, _ handler: @escaping (QLThumbnailReply?, Error?) -> Void) {
let imageURL = // ... put your own code here
let image = UIImage(contentsOfFile: imageURL.path)!
// size calculations
let maximumSize = request.maximumSize
let imageSize = image.size
// calculate `newImageSize` and `contextSize` such that the image fits perfectly and respects the constraints
var newImageSize = maximumSize
var contextSize = maximumSize
let aspectRatio = imageSize.height / imageSize.width
let proposedHeight = aspectRatio * maximumSize.width
if proposedHeight <= maximumSize.height {
newImageSize.height = proposedHeight
contextSize.height = max(proposedHeight.rounded(.down), request.minimumSize.height)
} else {
newImageSize.width = maximumSize.height / aspectRatio
contextSize.width = max(newImageSize.width.rounded(.down), request.minimumSize.width)
}
handler(QLThumbnailReply(contextSize: contextSize, currentContextDrawing: { () -> Bool in
// Draw the thumbnail here.
// draw the image in the upper left corner
//image.draw(in: CGRect(origin: .zero, size: newImageSize))
// draw the image centered
image.draw(in: CGRect(x: contextSize.width/2 - newImageSize.width/2,
y: contextSize.height/2 - newImageSize.height/2,
width: newImageSize.width,
height: newImageSize.height);)
// Return true if the thumbnail was successfully drawn inside this block.
return true
}), nil)
}
Upvotes: 3
Reputation: 1726
I've gotten the Thumbnail Extension rendering but it only displays its renders in the Files app (others use the App Icon) as far as I can tell.
It is important to note this issue with debugging extensions in that print to console and breakpoints may not be called even though the extension is running.
I see that you have the QLSupportedContentTypes set with your UTI but you may also want to change your UTI to something new as this is when it started working for me. I think after some testing the UTI can get corrupted. While it was working, I had a breakpoint set and it was never called.
Upvotes: 1