File Provider Extension trouble

Hi everyone,

I am a beginner in iOS/Swift programming. I'm trying to develop a mobile application that allows to mount a network drive in the iphone Files application via the WebDav protocol.

I saw on the internet that WebDav is no longer implemented in iOS because considered deprecated by apple.

To accomplish this task, I decided to separate responsibilities as follows:

Framework:

  • WebDav (responsible for communication with the WebDav server)

FileProviderExtension:

  • FileBridge (Responsible for bridging the gap between the WebDav Framework and the iOS Files app)

Main App

I also have an AppGroup that includes the main application and the fileproviderextension

Initially, to measure the feasibility and complexity of this task, I'd like to make a simplistic version that simply displays the files on my drive in the Files app, without necessarily being able to interact with them.

FileProviderExtension.swift:

import FileProvider
import WebDav

class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension {
    private var webDavService: WebDavService?

    required init(domain: NSFileProviderDomain)
    {
        super.init()
        self.webDavService = WebDavService(baseURL: URL(string: "https://www.mydrive.com/drive")!)
    }
    
    func invalidate() {
        // TODO: cleanup any resources
    }
    
    func item(for identifier: NSFileProviderItemIdentifier,
              request: NSFileProviderRequest,
              completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) -> Progress {
        let progress = Progress(totalUnitCount: 1)
        
        Task {
            do {
                if let items = try await webDavService?.propfind(path: identifier.rawValue, depth: 1),
                   let item = items.first(where: { $0.itemIdentifier == identifier }) {
                    completionHandler(item, nil)
                } else {
                    completionHandler(nil, NSError(domain: NSCocoaErrorDomain,
                                                   code: NSFileNoSuchFileError,
                                                   userInfo: nil))
                }
            } catch {
                completionHandler(nil, error)
            }
        }
        
        return progress
    }
    
    func fetchContents(for itemIdentifier: NSFileProviderItemIdentifier,
                       version requestedVersion: NSFileProviderItemVersion?,
                       request: NSFileProviderRequest,
                       completionHandler: @escaping (URL?, NSFileProviderItem?, Error?) -> Void) -> Progress {
        let progress = Progress(totalUnitCount: 1)
        
        Task {
            do {
                guard let service = webDavService else {
                    throw WebDavError.invalidResponse
                }
                
                let data = try await service.get(fileAt: itemIdentifier.rawValue)
                let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent(itemIdentifier.rawValue)
                try data.write(to: tempURL)
                
                completionHandler(tempURL, nil, nil)
            } catch {
                completionHandler(nil, nil, error)
            }
        }
        
        return progress
    }
    
    func createItem(basedOn itemTemplate: NSFileProviderItem, fields: NSFileProviderItemFields, contents url: URL?, options: NSFileProviderCreateItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress {
        // TODO: a new item was created on disk, process the item's creation
        
        completionHandler(itemTemplate, [], false, nil)
        return Progress()
    }
    
    func modifyItem(_ item: NSFileProviderItem, baseVersion version: NSFileProviderItemVersion, changedFields: NSFileProviderItemFields, contents newContents: URL?, options: NSFileProviderModifyItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (NSFileProviderItem?, NSFileProviderItemFields, Bool, Error?) -> Void) -> Progress {
        // TODO: an item was modified on disk, process the item's modification
        
        completionHandler(nil, [], false, NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:]))
        return Progress()
    }
    
    func deleteItem(identifier: NSFileProviderItemIdentifier, baseVersion version: NSFileProviderItemVersion, options: NSFileProviderDeleteItemOptions = [], request: NSFileProviderRequest, completionHandler: @escaping (Error?) -> Void) -> Progress {
        // TODO: an item was deleted on disk, process the item's deletion
        
        completionHandler(NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError, userInfo:[:]))
        return Progress()
    }
    
    func enumerator(for containerItemIdentifier: NSFileProviderItemIdentifier,
                    request: NSFileProviderRequest) throws -> NSFileProviderEnumerator {
        return FileProviderEnumerator(enumeratedItemIdentifier: containerItemIdentifier,
                                      service: webDavService)
    }
}

Here's the code I use to initialize my domain in the main app files:

fileprivate func registerFileProviderDomain() {
        let domainIdentifier = NSFileProviderDomainIdentifier("FileProviderExtension Bundle Identifier")
        let domain = NSFileProviderDomain(identifier: domainIdentifier,
                                          displayName: "My Drive")

        NSFileProviderManager.add(domain) { error in
            NSFileProviderManager.add(domain) { error in
            if let error = error {
                print("Error cannot add domain file provider : \(error.localizedDescription)")
            } else {
                print("Success domain file provider added")
            }
        }       
    }

I can't get rid of the Error : Error cannot add domain file provider : The operation couldn’t be completed. Invalid argument.

I don't know what I'm missing Please help me understand

Could you check the userInfo of the NSError returned on the addDomain completion handler? It may have debug information to help understand why you are encountering the issue.

File Provider Extension trouble
 
 
Q