首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用.fileimporter在SwiftUI中保存音频文件,检索文件并在SwiftUI列表中显示其文件名?

如何使用.fileimporter在SwiftUI中保存音频文件,检索文件并在SwiftUI列表中显示其文件名?
EN

Stack Overflow用户
提问于 2021-12-28 15:10:20
回答 1查看 57关注 0票数 1

我试图在这里找到一个类似的问题,但是找不到,所以,如何保存使用.fileimporter导入的音频文件,并将其保存在documents目录中的文件夹中。另外,如何检索它们并在SwiftUI中的列表中显示它们的文件名?我希望我的问题足够清楚。这是我试过的代码。

代码语言:javascript
运行
复制
import SwiftUI

extension FileManager {
    static func getDocumentsDirectory() -> URL {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return paths[0]
    }
    
    static let customFolderURL = FileManager.getDocumentsDirectory().appendingPathComponent("Music Files")
}

class Manager: ObservableObject {
    @Published var musicFiles: [URL] = []
    
    init() {
        do {
            try FileManager.default.createDirectory(at: FileManager.customFolderURL, withIntermediateDirectories: true, attributes: nil)
        } catch {
            print("Failed to create folder")
        }
    }
    
    func save(url: URL) {
        if url.startAccessingSecurityScopedResource() {
            do {
                let musicFile = try Data(contentsOf: url)
                try musicFile.write(to: FileManager.customFolderURL, options: .atomic)
                print("Success")
                print(FileManager.customFolderURL)
            } catch {
                print("Failed to save the music file")
            }
            url.stopAccessingSecurityScopedResource()
        } else {
            print("Permission failed!")
        }
    }
    
    func getMusicFiles() {
        do {
            let musicFiles = try FileManager.default.contentsOfDirectory(atPath: FileManager.customFolderURL.path)
            print(musicFiles)
        } catch {
            print("Failed to retrieve items.")
        }
    }
}

struct MainView: View {
    @State private var isFileImporterShown = false
    @State private var isMusicPlayerShown = false
    
    @EnvironmentObject var manager: Manager
    
    var body: some View {
        TabView {
            VStack {
                Button("Import Song") {
                    isFileImporterShown.toggle()
                }
                .padding()
                .fileImporter(isPresented: $isFileImporterShown, allowedContentTypes: [.audio], allowsMultipleSelection: true) { result in
                    do {
                        let url = try result.get().first!
                        if url.startAccessingSecurityScopedResource() {
                            manager.save(url: url)
                        }
                    } catch {
                        
                    }
                }
                
                Button("Show Player") {
                    isMusicPlayerShown.toggle()
                }
                .padding()
                .sheet(isPresented: $isMusicPlayerShown) {
                    MusicPlayerView()
                }
            }
            .tabItem {
                Image(systemName: "externaldrive")
                Text("Load")
            }
            
            AllSongsListView()
                .tabItem {
                    Image(systemName: "music.note.list")
                    Text("Songs")
                }
        }
    }
}

struct AllSongsListView: View {
    @EnvironmentObject var manager: Manager
    var body: some View {
        NavigationView {
            List {
                
            }
            .navigationTitle("Your Songs")
            .onAppear {
                manager.getMusicFiles()
            }
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-28 17:50:28

保存的问题在于您试图将文件保存为一个目录。

代码语言:javascript
运行
复制
try musicFile.write(to: FileManager.customFolderURL, options: .atomic)

因此,to参数是文件夹路径,而不是文件路径。

你需要像这样改变它:

代码语言:javascript
运行
复制
let savePath = FileManager.customFolderURL.appendingPathComponent(url.lastPathComponent)
                
try musicFile.write(to: savePath, options: .atomic)

为了显示导入的文件列表,您可以执行以下操作:

代码语言:javascript
运行
复制
List {
        ForEach(manager.musicFiles, id: \.self) { file in
            Text(file.lastPathComponent)
        }
}

以下是完整的示例:

代码语言:javascript
运行
复制
import SwiftUI

extension FileManager {
    static func getDocumentsDirectory() -> URL {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return paths[0]
    }
    
    static let customFolderURL = FileManager.getDocumentsDirectory().appendingPathComponent("Music Files")
}

class Manager: ObservableObject {
    @Published var musicFiles: [URL] = []
    
    static var shared = Manager()
    
    init() {
        do {
            try FileManager.default.createDirectory(at: FileManager.customFolderURL, withIntermediateDirectories: true, attributes: nil)
        } catch {
            print("Failed to create folder:")
            print(error)
        }
    }
    
    func save(url: URL) {
        if url.startAccessingSecurityScopedResource() {
            do {
                let musicFile = try Data(contentsOf: url)
                let savePath = FileManager.customFolderURL.appendingPathComponent(url.lastPathComponent)
                
                try musicFile.write(to: savePath, options: .atomic)
                print("Success")
                musicFiles.append(savePath)
            } catch {
                print("Failed to save the music file:")
                print(error)
            }
            url.stopAccessingSecurityScopedResource()
        } else {
            print("Permission failed!")
        }
    }
    
    func getMusicFiles() {
        do {
            let musicFiles = try FileManager.default.contentsOfDirectory(atPath: FileManager.customFolderURL.path)
            print(musicFiles)
        } catch {
            print("Failed to retrieve items.")
        }
    }
}

struct MainView: View {
    @State private var isFileImporterShown = false
    @State private var isMusicPlayerShown = false
    
    @ObservedObject var manager = Manager.shared
    
    var body: some View {
        TabView {
            VStack {
                Button("Import Song") {
                    isFileImporterShown.toggle()
                }
                .padding()
                .fileImporter(isPresented: $isFileImporterShown, allowedContentTypes: [.audio], allowsMultipleSelection: true) { result in
                    do {
                        let url = try result.get().first!
                        if url.startAccessingSecurityScopedResource() {
                            manager.save(url: url)
                        }
                    } catch {
                        print(error)
                    }
                }
                
                Button("Show Player") {
                    isMusicPlayerShown.toggle()
                }
                .padding()
                .sheet(isPresented: $isMusicPlayerShown) {
                    Text("Musiker")
                }
            }
            .tabItem {
                Image(systemName: "externaldrive")
                Text("Load")
            }
            
            AllSongsListView()
                .tabItem {
                    Image(systemName: "music.note.list")
                    Text("Songs")
                }
        }
    }
}

struct AllSongsListView: View {
    @ObservedObject var manager = Manager.shared
    
    var body: some View {
        NavigationView {
            List {
                ForEach(manager.musicFiles, id: \.self) { file in
                    Text(file.lastPathComponent)
                }
            }
            .navigationTitle("Your Songs")
            .onAppear {
                manager.getMusicFiles()
            }
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70508923

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档