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

相关推荐
ACP广源盛139246256737 小时前
iOS 27 开放 AI 生态@ACP#小型化扩展黄金风口,IX8008全面超越 ASM2806,铸就嵌入式 AI 扩展核心
人工智能·嵌入式硬件·macos·ios·计算机外设·objective-c·cocoa
人月神话Lee8 小时前
【图像处理】卷积原理与卷积核——图像处理的核心引擎
ios·ai编程·图像识别
用户2235862182010 小时前
如何在超大型的工程中使用 Claude Code?
前端·ios·claude
00后程序员张12 小时前
HTTPS单向认证、双向认证、抓包原理与反抓包策略详解
网络协议·http·ios·小程序·https·uni-app·iphone
Daniel_Coder15 小时前
iOS Widget 开发-14:iOS 18 控制中心组件开发
ios·swift·widget·activitykit·widgetkit·控制中心组件
七牛云行业应用15 小时前
OpenAI Codex手机版上线实战:iOS/Android 5步配置远程控制指南(2026)
android·ios·智能手机
2501_9159214317 小时前
使用Swift和Xcode创建简单iOS应用完整教程
ide·vscode·ios·个人开发·xcode·swift·敏捷流程
Daniel_Coder17 小时前
iOS Widget 开发-13:Live Activity 实战详解
ios·swift·widget·widgetkit·controls·live activity
库奇噜啦呼18 小时前
【iOS】Spotify项目总结
ios·iphone
鹤卿1231 天前
OC UI ——UIGestureRecognizer 手势识别
ui·ios·objective-c