swiftnsdocumentdirectory

Returning contents of file as Data in Swift


For the first time, I am trying to return a data file from documents. I am getting an error: No exact matches in call to initializer

Here's my code to retrieve the data file:

func returnGeoJsonFromDocumentsDirectory(eventId: String) -> Data{
    let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
    let filePath = paths.appendingPathComponent("\(eventId).json")
    let geoJsonFile = Data(contentsOfFile: filePath)
    if geoJsonFile != nil {
        return geoJsonFile!
    }
    else {
        print("Unable to return json")
        let emptyData = Data()
        return emptyData
    }

If I use NSData, this seems to solve the issue but I was under the impression you shouldn't NSData in Swift.


Solution

  • You are mixing up NS... with native Swift and String with URL related APIs.

    This is a pure Swift version preferring the URL related API

    func returnGeoJsonFromDocumentsDirectory(eventId: String) -> Data {
        let documentsFolderURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
        let fileURL = documentsFolderURL.appendingPathComponent(eventId).appendingPathExtension("json")
        do {
            return try Data(contentsOf: fileURL)
        } catch {
            print("Unable to return json", error)
            return Data()
        }
    }
    

    Or hand over the error to the caller

    func returnGeoJsonFromDocumentsDirectory(eventId: String) throws -> Data {
        let documentsFolderURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
        let fileURL = documentsFolderURL.appendingPathComponent(eventId).appendingPathExtension("json")
        return try Data(contentsOf: fileURL)
    }
    

    In iOS 16+, macOS 13+ there are new APIs to get the system folders in a sandboxed environment

    func returnGeoJsonFromDocumentsDirectory(eventId: String) throws -> Data {
        let documentsFolderURL = URL.documentsDirectory
        let fileURL = documentsFolderURL.appending(path: eventId).appendingPathExtension("json")
        return try Data(contentsOf: fileURL)
    }