簡體   English   中英

SwiftUI EnvironmentObject 不會重繪當前視圖,而是重繪其父視圖

[英]SwiftUI EnvironmentObject does not redraw the current view but its parent view

我試圖了解@EnvironmentObjectObservableObject中的屬性更改時如何影響重繪。

根據 Apple 關於EnvironmentObject的文檔,

每當可觀察對象發生變化時,環境對象都會使當前視圖無效。

如果上述陳述為真,那么當您按下ContentView中的按鈕時,下面的代碼不會使ChildView失效並重新創建。 這應該打印以下輸出。

initializing parent
initializing child
// after pressing the button
initializing child 

與我的上述假設相反,它實際上打印

initializing parent
initializing child
// after pressing the button
initializing parent 

誰能解釋為什么會這樣? 為什么ParentView被重新創建,即使ParentView不依賴於Library

class Library: ObservableObject {
  @Published var item: Int = 0
}

struct ContentView: View {
  @StateObject var library: Library = Library()
  var body: some View {
    VStack {
      ParentView()
        .environmentObject(library)
      Button {
        library.item += 1
      } label: {
        Text("increment")
      }
    }
  }
}

struct ParentView: View {
  init() {
    print("initializing parent")
  }
  var body: some View {
    VStack {
      Text("Parent view")
      ChildView()
    }
  }
}

struct ChildView: View {
  @EnvironmentObject var library: Library
  init() {
    print("initializing child")
  }
  var body: some View {
    Text("Child view")
  }
}

SwiftUI View 可能有點棘手。

每當可觀察對象發生變化時,環境對象都會使當前視圖無效。

並不意味着對象本身被重新創建。 它只是意味着視圖的主體被調用並且視圖自身重建。

請記住,結構不是View本身,它只是一個“描述”。

我添加了一些打印語句以使這一點更清楚:

struct ContentView: View {
    @StateObject var library: Library = Library()
    
    init(){
        print("initializing content")
    }
    
    var body: some View {
        VStack {
            let _ = print("content body")
            ParentView()
                .environmentObject(library)
            Button {
                library.item += 1
            } label: {
                Text("increment")
            }
        }
    }
}

struct ParentView: View {
    init() {
        print("initializing parent")
    }
    var body: some View {
        VStack {
            let _ = print("parent body")
            Text("Parent view")
            ChildView()
            
        }
    }
}

struct ChildView: View {
    @EnvironmentObject var library: Library
    init() {
        print("initializing child")
    }
    var body: some View {
        let _ = print("child body")
        Text("child")
    }
}

這最初打印:

initializing content
content body
initializing parent
parent body
initializing child
child body

按下按鈕后:

content body
initializing parent
child body

正如您所見,這些View的主體取決於Library ,它們各自的主體被重新評估。

ParentView初始化程序運行是因為在您的ContentView中,您在正文中調用ParentView() ,因此創建了一個“描述”您的 View 的新結構。 ParentView的視圖本身保持不變,因此不會調用其body var。

這個關於 SwiftUI 視圖的WWDC 2021視頻將幫助您更好地理解這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM