SwiftUI 中 ViewModel 的变化会引起 UI 的变化,如何能做到监听 ViewModel?常见的有如下几种方式。
@Published属性
代码语言:javascript复制class ContentViewModel: ObservableObject {
@Published var changingColor = Color.blue
init() {
Timer.scheduledTimer(
withTimeInterval: 1.0,
repeats: true,
block: { _ in
self.changingColor = self.randomColor()
}
)
}
private func randomColor() -> Color {
return Color(red: Double.random(in: 0.0 ... 1.0),
green: Double.random(in: 0.0 ... 1.0),
blue: Double.random(in: 0.0 ... 1.0))
}
}
struct ContentView: View {
@StateObject var viewModel = ContentViewModel()
var body: some View {
RoundedRectangle(cornerRadius: 20.0)
.frame(width: 100, height: 100)
.foregroundColor(viewModel.changingColor)
}
}
onchange Modifier
代码语言:javascript复制class ContentViewModel: ObservableObject {
@Published var changingColor = Color.blue
init() {
Timer.scheduledTimer(
withTimeInterval: 1.0,
repeats: true,
block: { _ in
self.changingColor = self.randomColor()
}
)
}
private func randomColor() -> Color {
return Color(red: Double.random(in: 0.0 ... 1.0),
green: Double.random(in: 0.0 ... 1.0),
blue: Double.random(in: 0.0 ... 1.0))
}
}
struct ContentView: View {
@StateObject var viewModel = ContentViewModel()
@State private var degrees = 0.0
var body: some View {
RoundedRectangle(cornerRadius: 20.0)
.frame(width: 100, height: 100)
.foregroundColor(viewModel.changingColor)
.rotationEffect(Angle.degrees(degrees))
.onChange(of: viewModel.changingColor, perform: { value in
degrees = 15
})
}
}
task Modifier
代码语言:javascript复制class ContentViewModel: ObservableObject {
@Published var changingColor = Color.blue
@Published var number = 0
init() {
Timer.scheduledTimer(
withTimeInterval: 1.0,
repeats: true,
block: { _ in
self.number = Int.random(in: 0 ... Int.max)
}
)
}
private func randomColor() -> Color {
return Color(red: Double.random(in: 0.0 ... 1.0),
green: Double.random(in: 0.0 ... 1.0),
blue: Double.random(in: 0.0 ... 1.0))
}
@MainActor
func randomColor() async {
changingColor = Color(red: Double.random(in: 0.0 ... 1.0),
green: Double.random(in: 0.0 ... 1.0),
blue: Double.random(in: 0.0 ... 1.0))
}
}
struct ContentView: View {
@StateObject var viewModel = ContentViewModel()
@State private var degrees = 0.0
var body: some View {
RoundedRectangle(cornerRadius: 20.0)
.frame(width: 100, height: 100)
.foregroundColor(viewModel.changingColor)
.rotationEffect(Angle.degrees(degrees))
.onChange(of: viewModel.changingColor, perform: { _ in
degrees = 15
})
.task(id: viewModel.number) {
await viewModel.randomColor()
}
}
}
Notification
代码语言:javascript复制class DataService {
static let notificationName = "CHANGE_SIZE"
static let sharedInstance = DataService()
private init() { }
func startService() {
// 不停发通知
Timer.scheduledTimer(
withTimeInterval: 2.0,
repeats: true, block: { _ in
NotificationCenter.default.post(
name: Notification.Name(
rawValue: DataService.notificationName),
object: nil)
})
}
}
class ContentViewModel: ObservableObject {
@Published var changingColor = Color.blue
@Published var isLargeSize = true
private var changeSizeMessageObserver: NSObjectProtocol?
init() {
Timer.scheduledTimer(withTimeInterval: 1.0,
repeats: true, block: { _ in
self.changingColor = self.randomColor()
})
// 收到通知
changeSizeMessageObserver =
NotificationCenter.default.addObserver(
forName: Notification.Name(
rawValue: DataService.notificationName),
object: nil,
queue: nil) { _ in
withAnimation {
self.isLargeSize.toggle()
}
}
}
deinit {
// 移除通知
if let obs = changeSizeMessageObserver {
NotificationCenter.default.removeObserver(obs)
}
}
private func randomColor() -> Color {
return Color(red: Double.random(in: 0.0 ... 1.0),
green: Double.random(in: 0.0 ... 1.0),
blue: Double.random(in: 0.0 ... 1.0))
}
}
struct ContentView: View {
@StateObject var viewModel = ContentViewModel()
var body: some View {
RoundedRectangle(cornerRadius: viewModel.isLargeSize ? 40 : 100)
.foregroundColor(viewModel.changingColor)
.frame(width: 200,
height: 200)
.onAppear(perform: {
DataService.sharedInstance.startService()
})
}
}