Search code examples
iosswiftfilestreamios-app-group

How to initialise an OutputStream with a Url?


I try to create an OutputStream to an app group folder, which is created as follows:

 func createProjectDirectoryPath(path:String) -> String
    {
        let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.xyz")
        let logsPath = containerURL!.appendingPathComponent(path)
        NSLog("12345- folder path: %@", logsPath.path)

        do {
            try FileManager.default.createDirectory(atPath: logsPath.path, withIntermediateDirectories: true, attributes: nil)
        } catch let error as NSError {
            NSLog("12345- Unable to create directory %@", error.debugDescription)
        }
        return logsPath.path
    }

This function gives me a path like this

/private/var/mobile/Containers/Shared/AppGroup/40215F20-4713-4E23-87EF-1E21CCFB45DF/pcapFiles

This folder exists, because the line FileManager.default.fileExists(path) returns true. The next step is to append a generated filename to the path, which I am doing here

let urlToFile = URL(string: createProjectDirectoryPath(path: "pcapFiles").appending("/\(filename)"))

which gives me the correct new path

/private/var/mobile/Containers/Shared/AppGroup/40215F20-4713-4E23-87EF-1E21CCFB45DF/pcapFiles/39CC2DB4-A6D9-412E-BAAF-2FAA4AD70B22.pcap

If I call this line, ostream is always nil

let ostream = OutputStream(url: urlToFile!, append: false)

Do I miss something? The OutputStream should create the file on this path, but for unknown reason, it is not possible.

PS: AppGroup is enabled in Capabilities and in developers console.


Solution

  • Your createProjectDirectoryPath() function returns a file path, therefore you must use URL(fileURLWithPath:) to convert that to an URL. Alternatively, modify your function to return an URL instead:

    func createProjectDirectoryPath(path:String) -> URL? {
        let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.xyz")
        let logsURL = containerURL!.appendingPathComponent(path)
        do {
            try FileManager.default.createDirectory(at: logsURL, withIntermediateDirectories: true)
        } catch let error as NSError {
            NSLog("Unable to create directory %@", error.debugDescription)
            return nil
        }
        return logsURL
    }
    

    In addition, you have to call open() on all Stream objects before they can be used, this will also create the file if it did not exist before:

    guard let logsURL = createProjectDirectoryPath(path: "pcapFiles") else {
        fatalError("Cannot create directory")
    }
    let urlToFile = logsURL.appendingPathComponent(filename) 
    guard let ostream = OutputStream(url: urlToFile, append: false) else {
        fatalError("Cannot open file")
    }
    ostream.open()