swiftUI状态管理

@state

用于当前视图的状态管理,@State的属性生命周期和当前视图保持一致

swift 复制代码
struct ContentView: View {
    @State private var isPlaying: Bool = false
    var body: some View {
        VStack {
            Button {
                isPlaying.toggle()
            } label: {
                Image(systemName: isPlaying ? "pause.circle" : "play.circle")
            }
        }
        .padding()
  

@binding

主要用于父子视图之间共享状态

swift 复制代码
// 子视图
struct PlayButton: View {
    
    @Binding var isPlaying: Bool
    
    var body: some View {
        Button(action: {
            self.isPlaying.toggle()
        }) {
            Image(systemName: isPlaying ? "pause.circle" : "play.circle")
        }
    }
}

// 父视图
struct ContentView: View {
    @State private var isPlaying: Bool = false
    var body: some View {
        VStack {
            Text("11111")
            Text("22222")
            PlayButton(isPlaying: $isPlaying)
        }
        .padding()
    }
}

@stateObject 和 @observedObject

先看一个例子:

主视图

点击button会更改视图的showRealName的状态,导致视图刷新

swift 复制代码
struct ContentView: View {
    @State private var showRealName = false
    var body: some View {
        VStack {
            Button("Toggle name") {
                showRealName.toggle()
            }
            Text("current user: \(showRealName ? "Harris" : "yiyi")")
            ScorePlate().padding(.top, 20)
        }
        .padding()
    }
}

ScorePlate

点击button改变model的score属性值

swift 复制代码
class Model: ObservableObject {
    init() {
        print("model created")
    }
    @Published var score: Int = 0
}
swift 复制代码
struct ScorePlate: View {
    
    @ObservedObject var model = Model()
    @State private var niceScore = false
    
    var body: some View {
        VStack {
            Button("+1") {
                model.score += 1
                if model.score > 3 {
                    niceScore = true
                }
                print("model.score = \(model.score)")
            }
            Text("score: \(model.score)")
            Text("Nice? \(niceScore ? "YES" : "NO")")
            ScoreText(model: model).padding(.top, 20)
        }
    }
}

ScoreText: 接收从外部传入的model,根据model中score的值更新文本

swift 复制代码
struct ScoreText: View {
    
    @ObservedObject var model: Model
    
    var body: some View {
        if model.score > 10 {
            return Text("fantastic")
        } else if model.score > 3 {
            return Text("Good")
        } else {
            return Text("mmmmm")
        }
    }
}

当多次点击+1 button时,score增加,ScorePlate和ScoreText都正常更新,但是当点击 Togglename 时,发现model的 init 方法再次执行,意味着model被重置了,score的值也被重置了,ScorePlate和ScoreText的状态都丢失了,这不是期望的结果。

原因:这是因为,和@state 这种底层存储被 SwiftUl"全面接管"的状态不同,@observedobject只是在View和Model之间添加订阅关系,而不影响存储。因此,当ContentView中的状态发生变化,ContentView.body 被重新求值时,ScorePlate就会被重新生成,其中的 model也一同重新生成,导致了状态的"丢失"。

解决办法:在ScorePlate中,把model的修饰符改为:@stateobject

相关推荐
健了个平_242 小时前
iOS 27 适配笔记
ios·xcode·wwdc
Tr2e2 小时前
🐱 从 0 到 1:用 Swift 手搓一个 macOS 桌面宠物(附源码)
macos·ios·swift
iOS开发上架哦5 小时前
Jenkins 自动上传 IPA 到 App Store 把发布步骤融入 CI/CD
后端·ios
ZJPRENO6 小时前
2026 苹果 WWDC 完整总结
ios
REDcker7 小时前
WWDC2026系统更新综述
macos·ios·开发者·apple·wwdc·ipados·wwdc2026
星星电灯猴8 小时前
全面解决Charles抓取HTTPS请求响应中文乱码问题的方法与技巧
后端·ios
人月神话-Lee8 小时前
【WWDC】Core AI:iOS 端侧大模型新纪元
人工智能·ios·ai·swift·wwdc·core ai
2501_916007479 小时前
iOS 开发工具选择指南 从编辑器、编译器到自动化构建
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
库奇噜啦呼10 小时前
【iOS】源码学习-YYModel源码学习
学习·ios·cocoa
风华圆舞10 小时前
一个 Flutter 项目同时保留 Android、iOS、HarmonyOS 支持的实践
android·flutter·ios