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

相关推荐
2501_915106323 小时前
H5 混合应用加密实践,从明文资源到安全 IPA 的多层防护体系
android·安全·ios·小程序·uni-app·iphone·webview
kdniao14 小时前
iOS应用集成物流API接口:架构设计、性能优化与用户体验实践指南
ios·性能优化·ux
2501_916007474 小时前
在 CICD 中实践 Fastlane + Appuploader 命令行,构建可复制的 iOS 自动化发布流程
android·运维·ios·小程序·uni-app·自动化·iphone
2501_915921435 小时前
从 HBuilder 到 App Store,uni-app 与 HBuilder 项目的 iOS 上架流程实战解析
android·ios·小程序·https·uni-app·iphone·webview
Sheffi666 小时前
Swift 与 OC 混编底层交互原理
ios·objective-c·swift
游戏开发爱好者86 小时前
以 uni-app 为核心的 iOS 上架流程实践, 从构建到最终提交的完整路径
android·ios·小程序·https·uni-app·iphone·webview
Sheffi667 小时前
iOS 内存分配机制:Malloc、VM、Dirty Memory
macos·ios·cocoa
游戏开发爱好者87 小时前
构建可落地的 iOS 性能测试体系,从场景拆解到多工具协同的工程化实践
android·ios·小程序·https·uni-app·iphone·webview
东坡肘子7 小时前
挖掘“沉默的专家” -- 肘子的 Swift 周报 #114
人工智能·swiftui·swift