簡體   English   中英

通過協議繼承的 SwiftUI 可重用視圖

[英]SwiftUI Reusable View via Protocol Inheritance

目標

我的目標是創建一個可重用的視圖協議,它繼承 SwiftUI 視圖協議並提供一些默認功能,用於根據視圖內容的狀態加載顯示不同的視圖。

這樣,我不必為我創建的每個視圖重寫相同的代碼並使代碼更清晰。

問題

我創建了一個“DelayedContentView”協議,它根據視圖的內容是否已加載來顯示兩個不同的視圖主體。 當我嘗試實現它時,問題就出現了。 “loadedBody”和“unloadedBody”屬性不能是“some View”類型,即使它們與 SwiftUI 視圖的 Body associatedType 的類型相同。

背景

我的應用程序中有各種視圖可以遠程獲取數據。 每個視圖顯示兩個視圖主體:一個用於獲取內容時,另一個用於獲取完成時。

Apple 的 SwiftUI 視圖協議

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
        }
    }
}

現在,您的特定視圖將聲​​明LoadedViewUnloadedView類型。 例如,在您的ExampleView ,它們都是Text ,而Body_ConditionalContent<Text,Text>

暫無
暫無

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

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