【问题标题】:Cannot use mutating member on immutable value: 'self' is immutable in SwiftUI不能在不可变值上使用变异成员:'self' 在 SwiftUI 中是不可变的
【发布时间】:2020-01-28 08:06:07
【问题描述】:

对于以下代码,我收到以下错误。我不知道如何解决这个问题。点击按钮后如何调用volumeCheck()

struct ContentView: View {

    var player = AVAudioPlayer()

    var body: some View {
        HStack {
            Button(action: {
                self.volumeCheck()
            }) {
                Text("Click to test chimes volume")
            }
        }
    }

    mutating func volumeCheck() {
        guard let url = Bundle.main.url(
            forResource: "chimes",
            withExtension: "mp3"
            ) else { return }

        do {
            player = try AVAudioPlayer(contentsOf: url)
            player.prepareToPlay()
            player.volume = Float(self.sliderValue)
            player.play()
        } catch let error {
            print(error.localizedDescription)
        }
        print("volume checked print")
    }
}

【问题讨论】:

  • 尝试让 player 成为 @State 变量。

标签: swiftui


【解决方案1】:

问题在于Viewstruct,而body 字段是具有非变异 getter 的计算属性。在您的代码中,它发生了在该非变异 getter 中调用的 mutating 方法。所以你需要做的就是把你的播放器放到某种模型上:

class Model {
    var player: AVPlayerPlayer()
}

struct ContentView: View {

    var model = Model()

    // player can be changed from anywhere
}

附:在某些其他情况下,您可能希望模型中的更改反映在视图中,因此您必须在模型声明之前添加 @ObservedObject。

希望有帮助

【讨论】:

    【解决方案2】:

    您正在尝试在 volumeCheck() 中将播放器设置为新对象。在初始化程序中设置播放器:

    struct ContentView: View {
    
        private var player: AVAudioPlayer?
    
        public init() {
            if let url = Bundle.main.url(forResource: "chimes",
                                         withExtension: "mp3") {
                self.player = try? AVAudioPlayer(contentsOf: url)
            }
        }
    
        var body: some View {
            HStack {
                Button("Click to test chimes volume") {
                    self.volumeCheck()
                    }   .disabled(player == nil)
            }
        }
    
        private func volumeCheck() {
            player?.prepareToPlay()
            player?.volume = Float(self.sliderValue)
            player?.play()
            print("volume checked print")
        }
    }
    

    请注意,您在代码中使用了 sliderValue,即使它没有在任何地方定义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-23
      • 1970-01-01
      • 2020-12-02
      • 2020-08-08
      • 2020-07-01
      • 1970-01-01
      相关资源
      最近更新 更多