微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Swiftui:使用文本字段用户输入重命名文档目录中的音频文件

如何解决Swiftui:使用文本字段用户输入重命名文档目录中的音频文件

我无法弄清楚如何重命名涉及多个视图的音频文件。我从 Voice Recorder App 找到了大部分代码,并尝试添加重命名功能,该功能接受来自用户点击编辑铅笔时触发的文本字段警报的用户输入。

  1. 在警报保存时,应从警报文本字段 userRecordingName(主 inputRecordingName 视图)更新 Communicator 属性
  2. 应触发警报保存 rename 功能RecordingsList 视图)
  3. renameRecordings 函数被触发(AudioRecorder 视图)
  4. 如果不为空,则使用新的 userRecordingName 字符串重新加载主视图中的记录行

我知道这很多,但是如果有人知道从文本字段重命名 URL lastPathComponent 并更新列表视图,那将非常有用!!

Main View

数据模型:

class Recording: ObservableObject {
    let fileURL: URL
    let createdAt: Date
    @Published var userRecordingName: String
    
    init(fileURL: URL,createdAt: Date,userRecordingName: String ) {
        self.fileURL = fileURL
        self.createdAt = createdAt
        self.userRecordingName = userRecordingName
    }  
}

主视图(需要 RecNameAlert 帮助):

struct Communicator: View {
    
    @Observedobject var audioRecorder: AudioRecorder = .shared
    @State var isPresented: Bool = false
    @State var inputRecordingName: String = ""
  
    var body: some View {
            NavigationView {
                ZStack{
                vstack {
                    HStack {
                        EditButton()
                    }
                    RecordingsList(audioRecorder: audioRecorder,isRenameClicked: $isPresented)
                    
                    if self.isPresented {
                    Button(action: {
                        self.isPresented = true
                    }) {
                            Image(systemName: "pencil.circle")
                    }.buttonStyle(BorderlessButtonStyle())
                    }
                    
                    if audioRecorder.recording == false {
                        Button(action: {print(self.audioRecorder.startRecording())}) {
                            Image(systemName: "circle.fill")
                        }
                    } else {
                        Button(action: {self.audioRecorder.stopRecording()}) {
                            Image(systemName: "stop.fill")
                        }
                    }
                } //End vstack
                    .navigationBarTitle("Voice recorder")
            
                    RecNameAlert(title: "Name Recording",isShown: $isPresented,inputRecordingName: $inputRecordingName,onSave: { text in
                        // ??? userRecordingName from Recording Object = text ???
                    })
                    
                    }// End ZStack
            }
        }
    }

录音提醒:

struct RecNameAlert: View {
    
    let screenSize = UIScreen.main.bounds
    
    var title: String = ""
    @Binding var isShown: Bool
    @Binding var inputRecordingName: String
    var onSave: (String) -> Void = { _ in}
    var onCancel: () -> Void = { }
    
    var body: some View {
        
        vstack {
            Text(title)
            TextField("",text: $inputRecordingName)
            .textFieldStyle(RoundedBorderTextFieldStyle())
            HStack{
                Button("Save") {
                    self.isShown = false
                    self.onSave(self.inputRecordingName)
                }
                Button("Cancel") {
                    self.isShown = false
                    self.onCancel()
                }
            }
        } // End vstack
            .padding()
            .frame(width: screenSize.width * 0.7,height: screenSize.height * 0.3)
            .background(Color(.lightGray))
            .clipShape(RoundedRectangle(cornerRadius: 20.0,style: .continuous))
            .offset(y: isShown ? 0 : screenSize.height)
            .animation(.spring())
            .shadow(color: Color(.white),radius: 6,x:-9,y:-9)
    }
}

录音列表和行:

struct RecordingsList: View {
    
   @Observedobject var audioRecorder: AudioRecorder = .shared
   @Observedobject var audioPlayer = AudioPlayer()
   @Binding var isRenameClicked: Bool
    
    var body: some View {
            List {
                ForEach(audioRecorder.recordings,id: \.createdAt) { recording in
                    RecordingRow(rowRecording: recording,isRenameClicked: self.$isRenameClicked )
                }// End For Each
                    .onDelete(perform: delete)
            } // End List
        } // End Body View
    
        func delete(at offsets: IndexSet) {
            
            var urlsToDelete = [URL]()
            for index in offsets {
                urlsToDelete.append(audioRecorder.recordings[index].fileURL)
            }
            audioRecorder.deleteRecording(urlsToDelete: urlsToDelete)
        }
        
        // ??? On save in the alert Box,I need to run this function ???
        func rename(at offsets: IndexSet) {

            var urlToRename = [URL]()
            for index in offsets {
                urlToRename.append(self.audioRecorder.recordings[index].fileURL)
            }
            audioRecorder.renameRecordings(urlToRename: urlToRename)
        }
    }

struct RecordingRow: View {

    @Observedobject var audioPlayer = AudioPlayer()
    @Observedobject var audioRecorder = AudioRecorder()
    @Observedobject var rowRecording: Recording
    @Binding var isRenameClicked: Bool
    
    var body: some View {
        HStack {
            vstack{
            // If userRecordingName not empty,present rowRecording.userRecodingName text instead of fileURL
            Text(self.rowRecording.fileURL.lastPathComponent)
            }
            Spacer()
            Button(action: {
                self.isRenameClicked = true
            }) {
                    Image(systemName: "pencil.circle")
            }.buttonStyle(BorderlessButtonStyle())
            
        } //End HStack
    }

AudioRecorder 和函数(播放、停止、删除重命名

import Foundation
import SwiftUI
import AVFoundation
import Combine

class AudioRecorder: NSObject,ObservableObject {
    
    override init() {
        super.init()
        fetchRecordings()
    }
    let objectwillChange = PassthroughSubject<AudioRecorder,Never>()
    var audioRecorder: AVAudioRecorder!
    static let shared = AudioRecorder()
    @Published var recordings = [Recording]()
    
    var recording = false {
        didSet {
            objectwillChange.send(self)
        }
    }
   //Folded
    func startRecording() { }
    
    func stopRecording() {}
    
    func fetchRecordings() {
        recordings.removeAll()
        
        let fileManager = FileManager.default
        let documentDirectory = fileManager.urls(for: .documentDirectory,in: .userDomainMask)[0]
        let directoryContents = try! fileManager.contentsOfDirectory(at: documentDirectory,includingPropertiesForKeys: nil)
        for audio in directoryContents {
            let recording = Recording(fileURL: audio,createdAt: getCreationDate(for: audio),userRecordingName: audio.lastPathComponent)
            recordings.append(recording)
        }
        recordings.sort(by: { $0.createdAt.compare($1.createdAt) == .orderedAscending})
        
        objectwillChange.send(self)
    }
    
    func deleteRecording(urlsToDelete: [URL]) {
        
        for url in urlsToDelete {
            print(url)
            do {
               try FileManager.default.removeItem(at: url)
            } catch {
                print("File Could not be deleted!")
            }
        }
        fetchRecordings()
    }
    // *Need Help Here*
    func renameRecordings(urlToRename: [URL]) {
            
            let fileManager = FileManager.default
            let documentDirectory = fileManager.urls(for: .documentDirectory,in: .userDomainMask)[0]
            
            for url in urlToRename {
                                //*Needs to be text variable from alert Box*
                let dstURL = documentDirectory.appendingPathComponent("NewName.m4a")
            do {
                try FileManager.default.moveItem(at: url,to: dstURL)
                try FileManager.default.removeItem(at: url)
            } catch {
                print(error.localizedDescription)
                }
        }
        fetchRecordings()
    }
} //End AudioRecorder

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?