第三章学习笔记-应用中的数据

Apr 23, 2024

100小时后请叫我苹果开发者

数据

@State

状态仅在当前定义所处的视图结构中有效(父级花括号内)。

@Binding

将父级视图结构中的信息传递到子级视图结构中。其作用并非创建一个新数据,而是单纯地将子级别视图中的信息与父视图结构的信息捆绑在一起。

struct ViewOne: View {
  @State var userInput = ""

  var body: some View {
    ViewTwo(userInput: $userInput )
  }
}

struct ViewTwo: View {
  // 绑定传递到的变量 userInput
  @Binding var userInput: String

  var body: some View {
    TextField("请输入用户名",text: $userInput)
      .textFieldStyle(RoundedBorderTextFieldStyle())
      .padding()
  }
}

@Environment

查询文档: EnvironmentValues | Apple Developer Documentation

写法: @Enviroment(\.valueName) var valueName

修改: 两种写法都可以

.enviroment(\.valueName, newValue)

.valueName(newValue)

@main
struct ForCreatorLifyCycleApp: App {
  @Enviroment(\.scenePhase) private var scenePhase

  // 修改
  EntryModalView()
    .enviroment(\.allowsTightening, true)
    .allowsTightening(true)
}

监测

可观察对象 ObservableObject 和发布器 @Published

可观察对象 ObservableObject 是一个协议 Protocol,该协议中要求所有遵守该协议的类必须包含发布器,当数据发生改变时,发布器会将被改变的信息传递出去。与其相对应的,属性包装器@Published的用途是标注哪些数据被改变时需要被发送,当数据改变时,发布器会自动将最新数据推送至所有订阅的视图中。

// 协议 ObservableObject
class Data: ObservableObject {
  //发布器 @Published
  @Published var article = "一篇文章"
}

观察对象@ObservedObject

观察对象指的是放置在视图文件中,用于订阅可观察对象的属性包装器。

struct ReactedView: View {
  // 订阅可观察对象Data
  @ObservedObject var data: Data

  var body: some View {
    Text(data.article)
  }
}

@main
struct SwiftUIViewsApp: App {
  // 初始化数据
  let data = Data()

  var body: some Scene {
    WindowGroup {
      ReactedView(data: data)
    }
  }
}

@ObservedObject 缺陷与变种:

  1. 初始化步骤稍显繁琐,能直接在需要用到的视图里直接初始化就会更方便。 -> @StateObject
  2. 不适合跨视图使用。 -> @EnvironmentObject

状态对象@StateObject

受限于 SwiftUI 的视图更新机制,若在视图中初始化 @ObservedObject 可能会造成异常刷新。为了解决这一问题,SwiftUI 可以负责协同初始化并管理该变量,新的属性包装器为 @StateObject

struct ReactedView: View {
  // 订阅可观察对象Data
  // @ObservedObject var data: Data
  // 改为
  @StateObject var data = Data()

  var body: some View {
    Text(data.article)
  }
}

环境对象@EnvironmentObject

解决 @ObservedObject 接力棒式数据传递。

具体写法如下,在最高层级的视图中把数据装到沙包里,写做.environmentObject(data) ,接着在任意子视图中接住沙包,写做@EnvironmentObject var data: Data便可以使用了。

// 考虑兼容 iOS 16 及之前的系统

struct ReactedView: View {
  // 在任意子视图中接住沙包
  @EnvironmentObject var data: Data

  var body: some View {
    Text(data.article)
  }
}

@main
struct SwiftUIViewsApp: App {
  // 订阅可观察对象Data
  // @ObservedObject var data: Data
  // 改为
   @StateObject var data = Data()

  var body: some Scene {
    WindowGroup {
        // 在最高层级的视图中把数据装到沙包里
      ReactedView(data: data)
           .environmentObject(data)
    }
  }
}

>

cd ..
CC BY-NC-SA 4.0 2024-PRESENT © Kelsey Shi