swiftavplayernsfilemanager

I cannot access a file I have just saved to my documents directory


Here is my saving and retrieving code:

func retrieveSong(songId: String) -> URL? {
        guard let pathComponent = cache[songId] else {
            return nil
        }
        if let documentsUrl = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: .documentsDirectory, create: false) {
            let fileUrl = documentsUrl.appendingPathComponent(pathComponent)
            
            if FileManager.default.fileExists(atPath: fileUrl.path()) {
                print("File Exists!\n\(fileUrl.absoluteString)")
            } else {
                print("File does not Exist!\n\(fileUrl.absoluteString)")
            }
            return fileUrl
        }
        return nil
    }
func cacheSong(song: Song, callback: @escaping () -> Void) {
        if self.cache[song.id] == nil {
            let url = SubsonicClient.shared.stream(id: song.id)
            Task {
                do {
                    let path = try await SubsonicClient.shared.downloadSong(url: url)
                    DispatchQueue.main.async {
                        self.cache[song.id] = path
                    }
                    print("Song cached: \(song.title)")
                    callback()
                } catch {
                    print("Song caching error: \(error)")
                }
            }
        }
    }


func downloadSong(url: URL) async throws -> String {
        let urlRequest = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData)
        let (data, response) = try await session.data(for: urlRequest)
        if let code = (response as? HTTPURLResponse)?.statusCode, code != 200 {
            printJSONData(data)
            throw HalpoError.badResponse(code: code)
        }
        let documentsURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: .documentsDirectory, create: false)
        let savedMusicPath = documentsURL.appendingPathComponent("saved", conformingTo: .directory)
        var isDirectory: ObjCBool = true
        if !FileManager.default.fileExists(atPath: savedMusicPath.path(), isDirectory: &isDirectory) {
            try FileManager.default.createDirectory(at: savedMusicPath, withIntermediateDirectories: false)
        }
        let pathComponent = "saved/\(UUID()).mp3"
        let filePath = documentsURL.appendingPathComponent(pathComponent)
        FileManager.default.createFile(atPath: filePath.path(), contents: nil)
        try data.write(to: filePath)
        return pathComponent
    }

and when I try to access this file via my retrieveSong function I get an error. logs:

Song cached: Funky Fanfare
["696b94e70f08c3023ed3c52ba0ff63f1": "saved/95381166-F33E-48AB-BA51-2CF931179BA2.mp3"]
File Exists!
file:///var/mobile/Containers/Data/Application/F04D1E83-7DAD-4690-8DA8-11FE3E2DEED3/Documents/saved/95381166-F33E-48AB-BA51-2CF931179BA2.mp3
AUDIO PLAYER ERROR: The file “95381166-F33E-48AB-BA51-2CF931179BA2.mp3” couldn’t be opened because you don’t have permission to view it.

I don't have anywhere I can really use url.startAccessingSecurityScopedResource() as the audio player is a library that does it all internally.

Also I don't believe I need to as I am working within the sandbox and the app has loaded files previously, I'm just not sure what has changed

Could the audio player, being in a swift package (SwiftAudioEX), not have permissions to view the documents directory?


Solution

  • After a while of messing about, I realised when loading my audio player item, I was using URL.absoluteString instead of URL.path()