[英]SwiftUI Reusable View via Protocol Inheritance
我的目標是創建一個可重用的視圖協議,它繼承 SwiftUI 視圖協議並提供一些默認功能,用於根據視圖內容的狀態加載顯示不同的視圖。
這樣,我不必為我創建的每個視圖重寫相同的代碼並使代碼更清晰。
我創建了一個“DelayedContentView”協議,它根據視圖的內容是否已加載來顯示兩個不同的視圖主體。 當我嘗試實現它時,問題就出現了。 “loadedBody”和“unloadedBody”屬性不能是“some View”類型,即使它們與 SwiftUI 視圖的 Body associatedType 的類型相同。
我的應用程序中有各種視圖可以遠程獲取數據。 每個視圖顯示兩個視圖主體:一個用於獲取內容時,另一個用於獲取完成時。
public protocol View {
associatedtype Body : View
var body: Self.Body { get }
}
protocol DelayedContentView:View {
func contentLoaded() -> Bool
var loadedBody: Self.Body { get }
var unloadedBody: Self.Body { get }
}
extension DelayedContentView {
//Default implementation that I won't have to rewrite for each view.
var body: some View {
if contentLoaded() {
return self.loadedBody
}else{
return self.unloadedBody
}
}
}
struct ExampleView:DelayedContentView {
func contentLoaded() -> Bool {
//Ask viewModel if content is loaded.
return false
}
var loadedBody: some View {
Text("Content is loaded.")
}
var unloadedBody: some View {
Text("Fetching content...")
}
}
Compile Error: Type 'ExampleView' does not conform to protocol 'DelayedContentView'
我認為協議繼承是處理這種情況的正確工具,但也許我錯了?
DelayedContentView
協議必須添加另外兩種關聯類型來表示兩種額外的視圖類型:一種用於“加載”視圖,另一種用於“卸載”。 它不能是Self.Body
因為它顯然會被侵犯,因為你需要在身體中有一個有條件的觀點。
protocol DelayedContentView: View {
associatedtype LoadedBody: View
associatedtype UnloadedBody: View
func contentLoaded() -> Bool
var loadedBody: LoadedBody { get }
var unloadedBody: UnloadedBody { get }
}
現在你有兩個這樣的泛型類型, Self.Body
將是這兩個類型的復合類型:
extension DelayedContentView {
@ViewBuilder // needed to create a _ConditionalContent type from if/else
var body: some View {
if contentLoaded() {
self.loadedBody
} else {
self.unloadedBody
}
}
}
現在,您的特定視圖將聲明LoadedView
和UnloadedView
類型。 例如,在您的ExampleView
,它們都是Text
,而Body
是_ConditionalContent<Text,Text>
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.