SwiftUI监听ViewModel变化

2024-03-10 08:04:39 浏览数 (4)

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()
            })
    }
}

1 人点赞