Home > Blockchain >  Able to call generic SwiftUI View when in my project but issues once it's in a package and impo
Able to call generic SwiftUI View when in my project but issues once it's in a package and impo

Time:09-14

I have a SwiftUI app that calls a View with passed in Views, methods, and variables. This view, let's call it DisplayView is general enough that I'm able to call it in different ways and have it display really different things. This worked great but I recently moved Display View to it's own package and I'm now having trouble calling it.

To create a simple example I started a new app and created a single general view to show how I call it. This WORKS.

// Shared Display View
public struct DisplayView<Content: View>: View {
    // The view we need to display
    let content: Content
    // The methods that need to be executed
    var aMethod: () -> Void
    
    // Boolean
    @Binding var aBoundVariable:Bool
    
    // Regular Variable
    var aName:String
    
    public var body: some View {
            content
#if os(macOS)
                .padding()
#endif
    }
}

Result of this:

Code shown along with app result when I call the general DisplayView located within my project.

When I instead move the DisplayView to it's own package and import it I'm having issues calling it.

First the newly formed DisplayView now looks like:


import SwiftUI

// Shared Display View for all the Core Data display views
public struct DisplayView<Content: View>: View {
    // The view we need to display
    let content: Content
    // The methods that need to be executed
    var aMethod: () -> Void
    
    // Boolean
    @Binding var aBoundVariable:Bool
    
    // Regular Variable
    var aName:String
    
    public init(content: any View, aMethod: @escaping () -> Void, aBoundVariable: Binding<Bool>, aName: String) {
        self.content = content as! Content
        self.aMethod = aMethod
        _aBoundVariable = aBoundVariable
        self.aName = aName
    }
    
    public var body: some View {
            content
#if os(macOS)
                .padding()
#endif
    }
}

I then committed,tagged, etc my package and imported it into the first app shown. I commented out the old DisplayView code, imported my package, and attempted to call the new DisplayView.

Code:

import SwiftUI
import thePackage

struct ContentView: View {

    @State var aVariable: Bool = false
    let aName = "hey"
    
    var body: some View {
        DisplayView(content: displayText(), aMethod: randomMethod, aBoundVariable: $aVariable, aName: aName)
    }

    private func randomMethod() {
        print("random method")
    }
    
    @ViewBuilder
    func displayText() -> some View {
        Text("Hello World!")
    }
}

//// Shared Display View --> Now using imported package
//public struct DisplayView<Content: View>: View {
// ...
//}

Just calling the method like before gets this error: Generic parameter 'Content' could not be inferred or image: Error: Generic parameter 'Content' could not be inferred

When I hit fix I see a placeholder

DisplayView<<#Content: View#>>(content: displayText(), aMethod: randomMethod, aBoundVariable: $aVariable, aName: aName)

but can't figure out how to use it properly. I've tried several iterations of all sorts including:

View using View some View some View and @ViewBuilder based on other questions I saw online. and @ViewBuilder based on other questions I saw online

I'd love to switch DisplayView into a package so I can use it in several projects but can't figure out how to call it properly when it's a package.

Thanks in advance for any help. :)

CodePudding user response:

You need to change your init to take Content instead of any View then it should work.

import SwiftUI

// Shared Display View for all the Core Data display views
public struct DisplayView<Content: View>: View {
    // The view we need to display
    let content: Content
    // The methods that need to be executed
    var aMethod: () -> Void
    
    // Boolean
    @Binding var aBoundVariable:Bool
    
    // Regular Variable
    var aName:String
    
    public init(content: Content, aMethod: @escaping () -> Void, aBoundVariable: Binding<Bool>, aName: String) {
        self.content = content
        self.aMethod = aMethod
        _aBoundVariable = aBoundVariable
        self.aName = aName
    }
    
    public var body: some View {
            content
#if os(macOS)
                .padding()
#endif
    }
}
  • Related