@ObservedObject,@State 和 @EnvironmentObject 有什么区别? SwiftUI Example

https://fandrian-rhamadiansyah.medium.com/swiftui-differences-between-observedobject-vs-stateobject-58eaf1a17fe Swift UI Property Wrappers

@State

struct ContentView: View {@State private var isRain = truevar body: some View {VStack {Image(systemName: isRain ? "cloud.rain.fill" : "sun.max.fill").resizable().frame(width: 100, height: 100)Text(isRain ? "我們淋著大雨不知何時才能放晴" : "太陽公公出來了,他對我呀笑呀笑")Button {isRain = Bool.random()} label: {Text("今天天氣如何 ?")}}}
}

struct 是赋值, class是引用

在struct 的计算属性(computed property)里,不允许改变成员变量

加上 @State 就可以改变了

参考:

用狀態設計 SwiftUI 畫面 — 認識 State property

sink

@Published  + @StateObject + @ObservedObject
+ @ObservableObject

可以在继承 ObservableObject 的struct或class 的变量加上 @Published 的 property。

当变量改变,将会自动更新页面

class Baby: ObservableObject {@Published var age = 1
}
struct ContentView: View {@ObservedObject var cuteBaby = Baby()var body: some View {VStack {Text("\(cuteBaby.age) 岁").font(.largeTitle).padding().background(Capsule().foregroundColor(.yellow))Button(action: {cuteBaby.age += 1}, label: {Text("baby大一岁")})}}
}

改版一下,加个子view

struct BabyView: View {@StateObject var cuteBaby = Baby()var body: some View {VStack {AgeText(cuteBaby: cuteBaby)Button(action: {cuteBaby.age += 1}, label: {Text("baby大一岁")})}}
}struct AgeText: View {var cuteBaby: Babyvar body: some View {Text("\(cuteBaby.age) 岁").font(.largeTitle).padding().background(Capsule().foregroundColor(.yellow))}
}

再点击button,岁数不会变化

问题出在 AgeText 不知道它的页面需要更新,在 property cuteBaby 前加上 @ObservedObject,这样 cuteBaby 的 age 变化,页面才会更新

struct AgeText: View {@ObservedObject var cuteBaby: Babyvar body: some View {Text("\(cuteBaby.age) 岁").font(.largeTitle).padding().background(Capsule().foregroundColor(.yellow))}
}

另外如果 Baby 的类型为 struct, 则不会有这个问题

struct Baby {var age = 1
}
struct ContentView: View {@State var cuteBaby = Baby()var body: some View {VStack {Image("baby").resizable().scaledToFit()AgeText(cuteBaby: cuteBaby)Button(action: {cuteBaby.age += 1}, label: {Text("一暝大一寸")})}}
}
struct AgeText: View {var cuteBaby: Babyvar body: some View {Text("\(cuteBaby.age) 歲").font(.largeTitle).padding().background(Capsule().foregroundColor(.yellow))}
}

@Binding

SwiftUI 有很多控件都是可以 Binding 的控件,比如 Toggle,TextField,Slider 等。binding 的中文是绑定的意思,binding 将绑定 view & model, 它们之间将会实现双向沟通的功能:

  • 操作控件,将会同步修改model内容
  • 操作model里的对象,也会同步更新控件

跟vue 里的 v-bind v-model 比较像

import SwiftUIstruct Raining: View {@State private var isRain = truevar body: some View {VStack{Image(systemName: isRain ? "cloud.rain.fill" : "sun.max.fill").resizable().frame(width:100, height:100)Text(isRain ? "下雨了,快回家收衣服!" : "天晴了,拿衣服去晒晒!")Toggle(isOn: $isRain) {Text("今天下雨吗?")}}.padding()}
}struct Raining_Previews: PreviewProvider {static var previews: some View {Raining()}
}

修改一下代码,去掉 &

            Toggle(isOn: isRain) {Text("今天下雨吗?")}

会提示错误

Cannot convert value 'isRain' of type 'Bool' to expected type 'Binding<Bool>', use wrapper instead

有binding的控件有:

  • TextField
  • Slider
  • DatePicker

也可以自己产生binding

Toggle(isOn: Binding(get: { isRain }, set: { isRain = $0 }), label: {Text("今天下雨嗎?")
})

SwiftUI 綁定資料的 Binding 元件

$0$1

swift自动为闭包提供参数名缩写功能,可以直接通过$0和$1等来表示闭包中的第一个第二个参数,并且对应的参数类型会根据函数类型来进行判断。如下代码:

let numbers = [1,2,5,4,3,6,8,7]
sortNumbers = numbers.sorted(by: { (a, b) -> Bool inreturn a < b
})
print("numbers -" + "\(sortNumbers)")
  • 使用$0,$1
let numbers = [1,2,5,4,3,6,8,7]
var sortNumbers = numbers.sorted(by: {$0 < $1})
print("numbers -" + "\(sortNumbers)")

参考

SwiftUI 產生 Binding 的各種方法

swift @State @Published+@StateObject+@ObservedObject+@ObservableObject+@Binding+$0$1相关推荐

  1. SwiftUI @State @Published @ObservedObject 深入理解和使用

    1.SwiftUI 是Apple 新出面向未来.跨多端解决方案.声明式编程 SwiftUI最新版本 2.0 但是需要 IOS 14 支持,多数现在还用的是IOS 13 所以很多不完善的东西都用Swif ...

  2. SwiftUI之深入解析@StateObject、@ObservedObject和@EnvironmentObject的联系和区别

    一.@State 属性包装器 ① 什么是 @State 属性包装器? 状态在任何现代应用程序中都是不可避免的,但在 SwiftUI 中,重要的是所有的视图都是它们状态的简单函数,我们不需要直接改变视图 ...

  3. SwfitUI之Published

    // let objectWillChange = PassthroughSubject<Void, Never>()// var brain: CalculatorBrain = .le ...

  4. 5.8 设计模式之State(状态)—对象行为型模式

    5.8 State(状态)-对象行为型模式 参考文章 意图 状态模式是一种行为设计模式, 改变一个对象的内部状态进而改变其行为. 问题及情景 状态模式与有限状态机的概念紧密相关. 其主要思想是程序在任 ...

  5. 以太坊EVM源码注释之State

    以太坊EVM源码注释之State Ethereum State EVM在给定的状态下使用提供的上下文(Context)运行合约,计算有效的状态转换(智能合约代码执行的结果)来更新以太坊状态(Ether ...

  6. 游戏陪玩平台源码开发,关于本地通知推送实现的详细解析

    游戏陪玩平台源码开发也是需要实现推送功能的,这样用户就能在第一时间了解平台消息以及好友发送的消息.这虽然只是一个小的方面,但却有着不容忽视的作用.今天我们主要了解一下利用系统的原生推送类结合工程实践如 ...

  7. 中改变了值但是数据没有刷新_SwiftUI数据流

    SwiftUI 中的界面是严格数据驱动的:运行时界面的修改,只能通过修改数据来间接完成,而不是直接对界面进行修改操作. 数据处理的基本原则 Data Access as a Dependency:在 ...

  8. swiftui_使用SwiftUI在30分钟内制作一个应用

    swiftui This post was first delivered as a live coding presentation at a Telstra Purple Back2Base ev ...

  9. SwiftUI3.0用户登录输入非空校验经典案例

    SwiftUI3.0用户登录输入非空校验经典案例 在oc和swift里面,通过UITextFiled的代理方法,可以实施监听到用户输入的每个字符,使用正则表达式,进行判断,是否合法.在swiftUI通 ...

最新文章

  1. 004-CSS3动画类
  2. 在我的网站上开通了WebPart演示和下载列表。
  3. 老赖名下无财产,可以执行老赖子女名下的财产吗?
  4. python中读取指定的行和列_Python怎么获取excle中指定行和列的值?
  5. GitHub下载代码方法
  6. Liferay7 BPM门户开发之10: 通用流程实现从Servlet到Portlet(Part1)
  7. 小学计算机属于数学与科学吗,我是计算机专业,想考小学信息技术教师资格证没有,那我是报科学还是...
  8. Spring MVC 全局异常处理(1) --HandlerExceptionResolver
  9. educoder 使用线程锁(lock)实现线程同步_Java8并发包源码分析:重入锁ReentrantLock和Condition实现原理...
  10. javaMail简介(一)
  11. asp.net c# 网页 导出excel 多表格 多个sheet
  12. ArcGIS:土地利用变化模式图绘制,土地利用转移矩阵
  13. hex文件、bin文件、axf文件的区别
  14. Latex表格排版大全 基于 IEEE双栏论文(设置单元格行列间距,自动换行设置)
  15. 怎样实现VLAN间通信,三种解决方案,一节课带你掌握
  16. 永恒之塔总是服务器未响应,《剑网3》《永恒之塔》怀旧服刚开上演“冲级热”,八月怀旧游戏集体搞事...
  17. access中本年度的四月一日_2014年3月计算机二级ACCESS上机试题及详解十二
  18. 数据挖掘里的“降维”----从五阶魔方的玩法思考
  19. 学习正则表达式 - 用 HTML 标记文本
  20. L2TP/IPSec 服务端安装

热门文章

  1. 不root怎么将FDex2反编译的dex文件拷出来
  2. speedoffice如何替换Word中的图片
  3. python axes函数_Python Matplotlib.axes.Axes.axvline()用法及代码示例
  4. Emiya 家今天的饭(CSP 2019 D2 T1)
  5. 足の痛いが続いて。。。
  6. 录制手机屏幕并且转换成GIF(手机,模拟器)
  7. 时序数据库TDengine基本概念和建模思路
  8. 安装程序未能打开日志文件_桌面安装工具日志记录错误的说明 - Office 365 | Microsoft Docs...
  9. 隐马尔可夫模型(HHM)学习笔记1
  10. 国内可以开展医疗器械管理体系(ISO13485)认证的机构名录