1、使用SwiftRealm会导致没法预览报Updating took more than 5 seconds
花了点时间查找问题,最后发现是因为初始化数据库写在AppDelegate,写在SceneDelegate就没事了!
2、SwiftUI数据流温故知新 - 属性包装
@State
@State属性允许修改Struct的属性,这些属性在普通的Struct里面是不允许修改的。当把@State放置到属性前,该属性实际上会被放到Struct的外部存储起来,这意味着SwiftUI能够随时销毁和重建Struct而不会丢失属性的值。
@State包装的属性通常是设置成私有的,不让外部使用。如果想让外部使用,则应该使用@ObservedObject和@EnvironmentObject,他们能够使外部修改属性后,状态能够得到改变。
建议把@State包装的属性都设置成私有
@Published
@Published是SwiftUI最有用的包装之一,允许我们创建出能够被自动观察的对象属性,SwiftUI会自动监视这个属性,一旦发生了改变,会自动修改与该属性绑定的界面。
1.首先需要遵循ObservableObject属性
class Bag: ObservableObject { var items = [String]() }
2.包装属性
class Bag: ObservableObject { @Published var items = [String]() }
这样就完成了。@Published包装会自动添加willSet方法监视属性的改变。
@ObservedObject
@ObservedObject告诉SwiftUI,这个对象是可以被观察的,里面含有被@Published包装了的属性。
@ObservedObject包装的对象,必须遵循ObservableObject协议。也就是说必须是class对象,不能是struct。
@ObservedObject允许外部进行访问和修改。
@EnvironmentObject
@EnvironmentObject包装的属性是全局的,整个app都可以访问
需要注意的是,不需要给定默认值,由于该属性是整个app都可以访问的,SwiftUI会自动的从环境中取出来。
当有这样一个场景,A->B->C->D->E->F,A界面的数据要传递给F界面,假如使用@ObservedObject包装,则需要一层一层传递,而使用@EnvironmentObject则不需要,直接在F界面,通过SwiftUI环境直接取出来就行。
需要注意的是,当界面显示时,就会去环境中取,但是,假如之前没有把属性放到环境中,则程序会崩溃。
@Environment
@Environment与@EnvironmentObject作用是不同的,@Environment是从环境中取出预定义的值,比如获得当前是暗黑模式还是正常模式,屏幕的大小等等。
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@Environment(\.managedObjectContext) var managedObjectContext
@Binding
@Binding也是非常重要的一个包装,声明一个属性是从外部获取的,并且与外部是共享的。相当于外部传过来的时候,不是传递的值。任何一方修改都会让SwiftUI的监视生效。
@GestureState
@GestureState能够让我们传递手势的状态,虽然使用@State也能实现,但@GestureState能让手势结束后我们回到最初的状态。
设置属性,设置zero意味着手势结束后,会回到最初的值。