美文网首页
[译]理解 SwiftUI 里的属性装饰器@State, @Bi

[译]理解 SwiftUI 里的属性装饰器@State, @Bi

作者: isnow | 来源:发表于2020-09-25 14:50 被阅读0次

    @State

    通过使用 @State 修饰器我们可以关联出 View 的状态. SwiftUI 将会把使用过 @State修饰器的属性存储到一个特殊的内存区域,并且这个区域和 View struct 是隔离的. 当 @State装饰过的属性发生了变化,SwiftUI 会根据新的属性值重新创建视图

    @Binding

    有时候我们会把一个视图的属性传至子节点中,但是又不能直接的传递给子节点,因为在 Swift 中值的传递形式是值类型传递方式,也就是传递给子节点的是一个拷贝过的值。但是通过 @Binding 修饰器修饰后,属性变成了一个引用类型,传递变成了引用传递,这样父子视图的状态就能关联起来了。
    struct ContentView: View{

        @State private var num:Int = 0; 

        var body: some View{

            VStack{

                Button("数字+1:\(num)")

                {

                    self.num += 1;

                }

                SubView(subCounter:$num)

            }

        }

    }

    struct SubView: View{

        @Binding var subCounter:Int

        var body: some View{

            VStack{

                Text("计数:\(subCounter)")

                Button("数字加一:\(subCounter)")

                {

                    self.subCounter += 1;

                }

            }

        }

    }

    @ObservedObject

    @ObservedObject 的用处和 @State 非常相似,从名字看来它是来修饰一个对象的,这个对象可以给多个独立的 View使用。如果你用 @ObservedObject 来修饰一个对象,那么那个对象必须要实现 ObservableObject 协议,然后用@Published 修饰对象里属性,表示这个属性是需要被 SwiftUI 监听的

    import Combine

    final class PodcastPlayer: ObservableObject {

        @Published private(set) var isPlaying: Bool = false

        func play() {

            isPlaying = true

        }

        func pause() {

            isPlaying = false

        }

    }
    这里定义了一个 PodcastPlayer 类,这个类可以给不同的 View 使用,SwiftUI 会追踪使用 View 里经过@ObservableObject修饰过的对象里进过 @Published 修饰的属性变换,一旦发生了变换,SwiftUI 会更新相关联的 UI
    struct EpisodesView: View {

        @ObservedObject var player: PodcastPlayer

        let episodes: [Episode]

        var body: some View {

            List {

                Button(

                    action: {

                        if self.player.isPlaying {

                            self.player.pause()

                        } else {

                            self.player.play()

                        }

                }, label: {

                        Text(player.isPlaying ? "Pause": "Play")

                    }

                )

                ForEach(episodes) { episode in

                    Text(episode.title)

                }

            }

        }

    }

    @EnvironmentObject

    从名字上可以看出,这个修饰器是针对全局环境的。通过它,我们可以避免在初始 View 时创建 ObservableObject, 而是从环境中获取 ObservableObject

    @Environment

    SwiftUI 本身就有很多系统级别的设定,我们开一个通过@Environment来获取到它们
    struct CalendarView: View {

        @Environment(\.calendar) var calendar: Calendar

        @Environment(\.locale) var locale: Locale

        @Environment(\.colorScheme) var colorScheme: ColorScheme

        var body: some View {

            return Text(locale.identifier)

        }

    }
    通过@Environment修饰的属性,我们开一个监听系统级别信息的变换,这个例子里一旦Calendar, Locale, ColorScheme发生了变换,我们定义的 CalendarView 就会刷新.

    相关文章

      网友评论

          本文标题:[译]理解 SwiftUI 里的属性装饰器@State, @Bi

          本文链接:https://www.haomeiwen.com/subject/zsdfuktx.html