gpt4 book ai didi

SwiftUI 观察变化

转载 作者:行者123 更新时间:2023-12-05 03:54:09 27 4
gpt4 key购买 nike

概述:

  • 我有一个名为 Player 的类和一个名为 Song 的类。
  • 播放器包含一首歌曲
  • 一个 View 正在显示歌曲标题

目标:

当我更改 player.song.title 时, View 需要更新。

问题:

当歌曲的属性改变时,它不会自动更新 View 。只有分配新歌曲时,更改才会反射(reflect)出来。

我的尝试:

我已经进行了 2 次尝试(下面的代码),都按预期工作。

问题:

  • 有更好的方法吗? (这似乎是一个常见的问题,人们会遇到。)我的尝试是否合理,尝试 2 是否更好?
  • 或者我的设计存在根本性缺陷? (我希望播放器中有这首歌,因为它代表当前歌曲)。

原始代码( View 不会更新):

型号

import Foundation
import Combine

class Player : ObservableObject {

@Published var duration = 0
@Published var song : Song

init(song: Song) {
self.song = song
}
}

class Song : ObservableObject {

@Published var id : Int
@Published var title : String
@Published var artist : String

init(id: Int,
title: String,
artist: String) {

self.id = id
self.title = title
self.artist = artist
}
}

查看

import SwiftUI

struct ContentView: View {

@ObservedObject var player : Player

var body: some View {

VStack {
Text(String(player.duration))
Text(player.song.title)
Text(player.song.artist)
}
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {

let song = Song(id: 1, title: "title1", artist: "artist1")
let player = Player(song: song)

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
player.song.title = "title2"
}

return ContentView(player: player)
}
}

尝试 1 - 使用 CombineLatest

问题:随着歌曲中属性数量的增加,它的可扩展性不是很好。

class Player : ObservableObject {

@Published var duration = 0
@Published var song : Song
private var songChangeCanceller : AnyCancellable?

init(song: Song) {
self.song = song

songChangeCanceller = song.$title.combineLatest(song.$artist, song.$id).sink { _, _, _ in
self.objectWillChange.send()
}
}
}

尝试2:使用objectWillChange.sink

class Player : ObservableObject {

@Published var duration = 0
@Published var song : Song

private var songChangeCanceller : AnyCancellable?
private var songAttributesChangeCanceller : AnyCancellable?

init(song: Song) {
self.song = song

songChangeCanceller = $song.sink { newSong in

self.songAttributesChangeCanceller = newSong.objectWillChange.sink { _ in
self.objectWillChange.send()
}
}
}
}

最佳答案

只需按如下方式简化模型,更新即可。使用 Xcode 11.4/iOS 13.4 测试

class Player : ObservableObject {

@Published var duration = 0
@Published var song: Song // published as soon as song.title changed

init(song: Song) {
self.song = song
}
}

struct Song : Identifiable { // value type
var id : Int
var title : String
var artist : String
}

关于SwiftUI 观察变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61249506/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com