Property Wrappers

  • 了解Swift和SwiftUI中的特色包装器
  • 一切SwiftUI的特色包装器的解说和比较
  • 存储暂时数据
  • 存储持久化数据
  • 读取环境数据
  • NameSpace
  • Application Delegate
  • 数据源的处理

概述

文章主要同享SwiftUI Modifier的学习进程,将运用案例的方法进行说明。内容浅显易懂,Property Wrappers介绍特色包装器,偏向理论,可以移步Github下载code -> github案例链接

1、了解Swift和SwiftUI中的特色包装器

SwiftUI严重依靠特色包装器来使咱们的代码更易于阅览、编写和维护。即便曾经不了解或者未运用过,但是在SwiftUI中有许多的@$符号,你或许会很疑问这是干嘛的?

特色包装器在Swift 5.1中引进的通用Swift功用,但比较于Swift,在SwiftUI中愈加的常见,比如@Published@ObservedObject和@EnvironmentObject等等,这都都是。特色包装器的基本状况:

  • 一些特色包装器可以完结原本不或许完结的效果,例如@State可以修正结构体的内部特色。
  • 某些特色包装器特别要求在其他当地完结额外的作业,假设该作业未完结,则或许会使运用程序溃散。例如@FetchRequest的运用条件将CoreData的保管方针context放入环境中。
  • 一次只能运用一个特色包装器,那么@ObservedObject @Binding var value = SomeClass()是差错的声明。
  • 尽管有些特色包装器看起来非常相似,但是效果是不同的,要在正确的场景运用它们,比如@Environment和@EnvironmentOjbect
  • 在某些特定状况下,还可以创建自己的特色包装器。

2、一切SwiftUI的特色包装器的解说和比较

SwiftUI供应了17个特色包装器,每个特色包装器都供应了不同的功用,正确的运用特色包装器太重要了。简明描绘特色包装器的效果,是否具有其数据(处理数据的才干):

称谓 描绘 是否持有数据
@AppStorage 从UserDefaults读取和写入值
@Binding 指的是不同视图具有的值类型数据。更改本地绑定也会更改长途数据
@Environment 可以在系统读取数据,例如配色计划、可拜访性选项和特征集结,但假设需求,可以在此处增加自己的键
@EnvironmentObject 读取放入环境中的同享方针
@FetchRequest 发动特定实体的中心数据获取恳求
@FocusedBinding 在监督要害窗口的值,例如其时选定的文本字段
@FocusedValue 是一个简易版本的@FocusedBinding
@GestureState 存储与其时正在进行的手势相关的值,例如滑动距离,当手势间断时重置为默许值
@Namespace 创建一个动画命名空间以容许匹配集结效果,该效果可以由其他视图同享
@NSApplicationDelegateAdaptor 用于创建一个类并将其注册为macOS运用程序Delegate
@ObservedObject 指的是符合协议的外部类的实例ObservedObject
@Published 附加到ObservableObject内的特色,并告知SiftUI在数据更改时改写运用此特色的任何视图
@ScaledMetric 读取用户的动态类型设置并依据供应的原始值当大或缩小数字
@SceneStorage 可以保存和恢复少量数据以进行状况的恢复(比如前后台切换)
@State 在本地视图操作少量的值类型数据
StateObject 用于存储符合ObservableObject协议的引用类型数据的新实例
@UIApplicationDelegateAdaptor 用于创建一个类并将其注册为iOS运用程序的AppDelegate

3、存储暂时数据

3.1、@State与@Binding区别

当触及到在程序中存储数据时,最简略的特色包装器是@State,它旨在存储视图在本地运用的值类型,因此非常适合存储Int、Bool和Struct的实例

比较之下,@Binding用于希望更改但不由视图具有的简略数据。例如,Toggle作业原理:它需求在打开和关闭状况之间切换,但不希望自己存储该值,因此会绑定到视图具有的某个外部值。所以,视图具有@State特色,而Toogle具有@Binding特色。

还有一种称为@GestureState的@State的变化,专门用于跟踪Active手势。运用频率不高,但是此特色包装器的优势在于在手势结束时将特色重置为其初始值。

关于更高档的用途,即处理类在许多当地同享数据,不应运用@State和@Binding。相反,应该在某处运用@StateObject创建方针,然后在其他视图运用@ObservedObject声明特色。

总结:
一个简略的规则是:假设在特色包装器的称谓中只需包含“state”,也便是@*State,就清晰了其时视图具有数据。

因此,@State表明简略的值类型在本地的创建与处理,但或许运用@Binding在其他当地同享,而@StateObject表明引用类型数据在本地创建和处理,可以在其他的当地运用@ObservedObject进行数据同享。

3.2、 不好案例

这非常重要:假设看到@ObservedObject var something = SomeType(),尽管在编译期不会报错,但是存在较大的隐患,在此处运用@ObservedObject声明并给变量初始化,或许会因为方针被提前销毁然后导致运用程序的溃散。看到这样的声明,肯定要更改为@StateObject来修饰,这样SwiftUI就知道视图具有此数据,而不是引用它。

@ObservedObject var something = SomeType()
修正为
@StateObject var something = SomeType()

3.3、@EnvironmentObject

假设要将相同的数据从一个视图传递到另一个视图,那么运用@EnvironmentObject将非常有用,因为它可以从同享环境中读取引用类型方针,而不是清晰要传递它。

就像ObservableObject相同,@EnvironmentObject不应该用于初始方针的创建。相反,应该在不同的视图中运用它,并运用environmentObject()修饰符将其注入到环境中。尽管环境会自动坚持你的方针的一切权,但你也可以运用@StateObject将其存储在最初创建的当地。但这并不是有必要的过程。将方针放入到环境中足以使其在不进一步获得一切权的状况下坚持生动状况。

最终一个依据状况的特色包装器是@Published,它用于在你的引用类型内符号特色。任何运用@Published符号的特色都会在值改动时导致其一切引用的视图发生改写。

4、存储持久化数据

在SwiftUI中,有三个特色包装器用于存储或检索数据:

  • @AppStorage,它是UserDefaults的封装器,每次从运用存储中读取或写入值,实际上在读取和写入UserDefaults。
  • @SceneStorage,它是围绕Apple的状况恢复API的封装器。状况恢复时运用程序关闭并从头加载,并回到用户离开时的相同状况的机制。这使得运用看起来像在一向工作,其实在后台已经被静静关闭了。
  • @FetchRequest,用于从CoreData中检索信息,将自动运用环境中任何保管方针的context,并在底层数据发生更改时更新自身。

尽管@AppStorage和@SceneStorage看起来相似,但他们并不相同:@AppStorage为整个运用程序存储一个值,而@SceneStorage会自动为同一数据的多个值保存多次,以应对用户多次打开运用程序窗口的状况(iPadOS与macOS场景)

因此,运用AppStorage来存储大局值(不是那么重要的数据),比如“用户现在心境怎么样”,而运用@SceneStorage用来存储“用户其时正在浏览哪个页面”

@AppStorage和@SceneStorage不安全,不可以用于存储敏感数据。

5、读取环境数据

SwiftUI供应了两个特色包装器用于读取用户的环境数据:@Environment@ScaledMetric

  • @Environment用于读取各种数据,例如其时active的特征集结是什么,用户是否运用了2x或3x的屏幕,所在时区是什么等。他还具有一些特殊的运用程序操作,例如导出文件和在系统注册的网络浏览器中打开URL。条件是你需求知道你要运用的系统环境变量的selector。

  • @ScaledMetric运用要愈加简略,它依据用户的动态类型设置来调整用户界面的大小。例如,一个大小为100*100的框在运用系统默许大小时看起来很好,但运用@ScaledMetric后,当启用较大的动态类型设置时,自动编程200*200。

6、NameSpace

SwiftUI供应了@Namespace特色包装器,它可以为动画创建一个新的命名空间。比如对id为5的视图进行动画处理。可以经过运用特色类型Namespace.ID并从创建它的视图注入@Namespace值在视图之间同享命名空间。这可以在视图之间创建匹配的集结教过动画,而不用在其时视图中存储一切数据。

7、Application Delegate

假设想在SwiftUI中拜访旧的UIApplicationDelegate和NSApplicationDelegate方法及告知,可以分别运用@UIApplicationDelegateAdaptor@NSApplicationDelegateAdapotr特色包装器创建对应的类。
而且还需求供应这些包装器的参数是AppDelegate的类,他们会确保创建一个实例并将恰当的告知发送给他。

8、数据源的处理

之前我描绘了那些特色包装器具有它的数据源,实际上这触及到你的运用程序中的数据源:具有他们的数据的包装器是数据源,因为他们创建和处理值,而不具有他们的数据的包装器不是数据源,因为他们从其他当地获得数据。

具有数据的特色包装器(直接创建和处理值):

  • @AppStorage
  • @FetchRequest
  • @GestureState
  • @Namespace
  • @Published
  • @ScaledMetric
  • @SceneStorage
  • @State
  • @StateObject
  • @NSApplicationDelegateAdaptor
  • @UIApplicationDelegateAdaptor

未具有数据源的特色包装器(在其他当地获取值):

  • @Binding
  • @Environment
  • @EnvironmentObject
  • @FocusedBinding
  • @FocusedValue
  • @ObservedObject

9、关于特色包装器的总结

关于这么多的特色包装器或许看起来有点烦,所以只需记住以下两点就可以很舒服搞SwiftUI了

  • 假设想创建一个由其时视图具有的心特色,值类型运用@State修饰,引用类型运用@StateObject修饰。

  • 假设想引用在其他当地创建的值,值类型运用@Binding,运用类型运用@ObservedObject或@EnvironmentObject