在 SwiftUI 中播放音频时无法更新行颜色

Posted

技术标签:

【中文标题】在 SwiftUI 中播放音频时无法更新行颜色【英文标题】:Cannot update row color while playing audio, in SwiftUI 【发布时间】:2021-04-29 09:01:49 【问题描述】:

在使用SwiftUI 开发ios 应用程序时,我面临以下情况。我已经设置了一个自定义环境键。这是 SceneDelegate.swift 文件中的相关代码。

private struct RowColorMaster: EnvironmentKey 
    static var defaultValue: Binding<[[String:Color]]> = .constant([[:]])


extension EnvironmentValues 
    var rowColorMasterDico: Binding<[[String:Color]]> 
        get self[RowColorMaster.self]
        set self[RowColorMaster.self] = newValue
    



class SceneDelegate: UIResponder, UIWindowSceneDelegate 
    var window: UIWindow?
    var rowColorMasterDico:[[String:Color]] = []

    func scene(_ scene: UIScene, 
               willConnectTo session: UISceneSession, 
               options connectionOptions: UIScene.ConnectionOptions) 
        .....
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        .....
        rowColorMasterDico = .....

        print("rowColorMasterDico -> \(rowColorMasterDico.count)")

        let contentView = ContentView(sectionsList: sectionsList,
                                      itemMasterList: sentceMasterArray)
                                .environment(\.managedObjectContext, context)
                                .environment(\.rowColorMasterDico,
                                             Binding(get: self.rowColorMasterDico,
                                                     set: 
                                                        newValue in
                                                        self.rowColorMasterDico = newValue
                                                     ))
        .....
    
    .....

然后再往下,在视图层次结构中,在某个视图文件中:

struct SectionView: View 
    var moc:NSManagedObjectContext
    .....
    @Environment(\.rowColorMasterDico) var rowColorMasterDico
    .....

    func handleEvent(_ file: String, flag: Bool) 
        // This function is called when an audio file
        // starts or ends playing.
        if rowColorMasterDico.wrappedValue.count != 10 
            // This should not happen! But for some reason it sometimes does.
            print("rowColorMasterDico is messed up !")
            return
        

        // Check that rowColorMasterDico.wrappedValue[page.index][file] changes value.
        print("CLR(Before)=\(rowColorMasterDico.wrappedValue[page.index][file]!)")
        rowColorMasterDico.wrappedValue[page.index][file] = flag ? Color.red : Color.white
        print("CLR(After)=\(rowColorMasterDico.wrappedValue[page.index][file]!)")
    
    .....


    var body: some View 
        VStack 
            ListItemView(itemList: itmMstrList[page.index], moc: moc,
                         rowColorDico: rowColorMasterDico.wrappedValue[page.index])
            Button(action: 
                if !soundManager.isPlaying self.playAllAudio(itmMstrList[page.index])
                else soundManager.stopAudio()
            )
            
                Image(uiImage: UIImage(named: "speaker.png")!)
                    .padding(.bottom, 17)
            
        
    
    .....


struct ListItemView: View 
    let crnrRad:CGFloat = 13.0, bgGreyLvl = 0.37, fgGreyLvl = 0.93
    var itemList:[ItemList], moc:NSManagedObjectContext
    @State var rowColorDico:[String:Color]

    .....
    
    func didDismiss() 
        // Handle the dismissing action.
        print(#function)
    
    
    var body: some View 
        List 
            ForEach(self.itemList) 
                item in
                HStack 
                    Spacer()
                    Button(action: 
                        self.handleRowItem(item)
                    )
                    
                        RowItemView(expression: item.expression!,
                                    fgTxtColor: rowColorDico[item.soundFile!] ?? Color.orange)
                    
                    Spacer()
                
            
        .sheet(item: $itemPage, onDismiss: didDismiss) 
            sntnc in
            .....
        
        
    



struct RowItemView: View 
    var expression:String
    @State var fgTxtColor:Color
    let crnrRad:CGFloat = 13.0, bgGreyLvl = 0.37
    
    var body: some View 
        Text(expression)
            .foregroundColor(fgTxtColor)
            .font(.headline)
            .padding(.horizontal, 11).padding(.vertical, 15)
            .background(Color(.sRGB, red: bgGreyLvl, green: bgGreyLvl,
                              blue:bgGreyLvl, opacity: 1.0))
            .cornerRadius(crnrRad)
            .overlay(RoundedRectangle(cornerRadius: crnrRad)
                    .stroke(Color.yellow, lineWidth: 3))
    

这就是问题所在。当我在 ListItemView 中播放音频文件列表时,匹配的行项目应该改变播放文件的颜色。为此的工作是在 handleEvent 函数中完成的,我可以检查这是否按预期发生。但是列表中显示的颜色并没有改变。这是为什么呢?

是不是我设置环境变量rowColorMasterDico的方式有误? 还是我错过了其他东西?我已经尝试了上面代码的许多不同变体,但我无法使其工作。我希望有人会在某个地方看到并指出错误。

【问题讨论】:

【参考方案1】:

以防万一这对其他人有用,我想报告我通过参考this 解决了我的问题,同时再看一下我自己的代码。

【讨论】:

以上是关于在 SwiftUI 中播放音频时无法更新行颜色的主要内容,如果未能解决你的问题,请参考以下文章

无法播放网络音频文件

在swiftui中按钮的触摸动作播放音频

无法使用 MediaPlayer 对象在 Android 中播放许多音频文件

音频设备测试无法播放声音

Discord Bot 更新:如何播放音频?

播放时无法让范围滑块与音频一起移动