File Provider iOS11 startProvidingItem not invoked

I'm implementing a File Provider Extension for iOS 11.

Dispite watching the conference at https://developer.apple.com/videos/play/wwdc2017/243/ and navigating through Apple's Documentation, I still can't seem to understand how to implement some of the methods for NSFileProviderExtension and NSFileProviderEnumerator objects.

I successfully implemented NSFileProviderItem, having all of them listed in the Navite iOS 11 Files App. However, I can't trigger any document based app to open upon selecting a file.

I overrided all the methods for the NSFileProviderExtension. Some are still empty, but I placed a breakpoint to check whenever they are called.

The NSFileProviderExtension looks something like this:

class FileProviderExtension: NSFileProviderExtension {
    var db : [FileProviderItem]  = [] //Used "as" a database
...

    override func item(for identifier: NSFileProviderItemIdentifier) throws -> NSFileProviderItem {
        for i in db {
            if i.itemIdentifier.rawValue == identifier.rawValue {
                return i
            }
        }
        throw NSError(domain: NSCocoaErrorDomain, code: NSNotFound, userInfo:[:])
    }

    override func urlForItem(withPersistentIdentifier identifier: NSFileProviderItemIdentifier) -> URL? {
        guard let item = try? item(for: identifier) else {
            return nil
        }

        // in this implementation, all paths are structured as <base storage directory>/<item identifier>/<item file name>
        let manager = NSFileProviderManager.default
        let perItemDirectory = manager.documentStorageURL.appendingPathComponent(identifier.rawValue, isDirectory: true)

        return perItemDirectory.appendingPathComponent(item.filename, isDirectory:false)
    }

    // MARK: - Enumeration
    func enumerator(for containerItemIdentifier: NSFileProviderItemIdentifier) throws -> NSFileProviderEnumerator {
        var maybeEnumerator: NSFileProviderEnumerator? = nil

        if (containerItemIdentifier == NSFileProviderItemIdentifier.rootContainer) {
            maybeEnumerator = FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier)
            self.db = CustomData.getData(pid: containerItemIdentifier)

        } else if (containerItemIdentifier == NSFileProviderItemIdentifier.workingSet) {
            // TODO: instantiate an enumerator for the working set
        } else {

        }
        guard let enumerator = maybeEnumerator else {
            throw NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:])
        }
        return enumerator
    }

My enumerateItems looks something like so:

class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {

    override func enumerateItems(for observer: NSFileProviderEnumerationObserver, startingAt page: NSFileProviderPage) {

        let itens = CustomData.getData(pid: enumeratedItemIdentifier)
        observer.didEnumerate(itens)
        observer.finishEnumerating(upTo: nil)

    }

The static function CustomData.getData is used for testing. It returns an array of NSFileProviderItem with the desired properties. It should be replaced with a database, as explained in the conference.

class CustomData {


    static func getData(pid : NSFileProviderItemIdentifier) -> [FileProviderItem] {
        return [
            FileProviderItem(uid: "0", pid: pid, name: "garden", remoteUrl : "https://img2.10bestmedia.com/Images/Photos/338373/GettyImages-516844708_54_990x660.jpg"),
            FileProviderItem(uid: "1", pid: pid, name: "car", remoteUrl : "https://static.pexels.com/photos/170811/pexels-photo-170811.jpeg"),
            FileProviderItem(uid: "2", pid: pid, name: "cat", remoteUrl : "http://www.petmd.com/sites/default/files/what-does-it-mean-when-cat-wags-tail.jpg"),
            FileProviderItem(uid: "3", pid: pid, name: "computer", remoteUrl : "http://mrslamarche.com/wp-content/uploads/2016/08/dell-xps-laptop-620.jpg")
        ]
    }

}

The problem is, when the user presses a document, urlForItem is successfully called but nothing happens upon returning the item url.

What am I doing wrong? I can't find any examples on the internet.

Cheers

-nls

1 answer

  • answered 2017-10-11 09:58 nfls

    Turns out, I did not correctly implement providePlaceholder(at url:).

    It is now solved.

    Cheers

    -nls