SwiftUI:无法使用参数将View传递到CustomView中

huangapple go评论71阅读模式
英文:

SwiftUI: Unable to pass View into CustomView using Parameters

问题

I'm currently having issues with sending a custom view through into another view as a parameter. All the other parameters work perfectly, it's just the view.

I've set up everything within a single Swift file to encapsulate the environment to troubleshoot, but I just get:
Cannot convert value of type 'Text' to expected argument type 'some View'

I'm most likely just missing something obvious, but I've tried with both any/some View, as well as variants with and without the @ViewBuilder but can't seem to find a solution.

Here's my code:

//
//  ProductsTabButton.swift
//  RM Product Guide
//
//  Created by Matthew Hardiman on 04/07/2023.
//

import SwiftUI

struct ProductsTabButton: View {
    
    @State var sheetActiveBool: Bool = false
    var dismissFunction: () -> Void
    var buttonColor: String = "rmWhite"
    var buttonText: String = "Button Text"
    var buttonIcon: String = "list.dash"
    var buttonView: some View = BackgroundView()
    
    
    var body: some View {
        
        // BUTTON STYLING
        Button(action: {
            sheetActiveBool.toggle()
        },label:{
            VStack(spacing: 0){
                Image(systemName: buttonIcon).productLinkBlockImage()
                Text(buttonText).productLinkBlockText()
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(Color(buttonColor))
        })
        .sheet(isPresented: $sheetActiveBool, onDismiss: dismissFunction) {
            fetchView()
        }
        
    }
    
    
    @ViewBuilder
    func fetchView() -> some View {
         buttonView
    }
}

struct ProductsTabButton_Previews: PreviewProvider {
    static var previews: some View {
        ProductsTabButton(
            dismissFunction: {
                print("Test")
            },
            buttonColor: "rmYellow",
            buttonText: "Yellow",
            buttonIcon: "list.star",
            //buttonView: SearchView()
            buttonView: Text("Test")
        )
    }
}

Any help with this would be greatly appreciated.

Thank you!

英文:

i'm currently having issues with sending a custom view through into another view as a parameter. All the other parameters work perfectly, it's just the view.

I've setup everything within a single swift file to encapsulate the enviroment to trouble shoot but i just get:
Cannot convert value of type 'Text' to expected argument type 'some View'

I'm most likely just missing something obvious, but i've tried with both any/some View, as well as variants with and without the @ViewBuilder but can't seem to find a solution.

Here's my code:

//
//  ProductsTabButton.swift
//  RM Product Guide
//
//  Created by Matthew Hardiman on 04/07/2023.
//

import SwiftUI

struct ProductsTabButton: View {
    
    @State var sheetActiveBool: Bool = false
    var dismissFunction: () -> Void
    var buttonColor: String = "rmWhite"
    var buttonText: String = "Button Text"
    var buttonIcon: String = "list.dash"
    var buttonView: some View = BackgroundView()
    
    
    var body: some View {
        
        // BUTTON STYLING
        Button(action: {
            sheetActiveBool.toggle()
        },label:{
            VStack(spacing: 0){
                Image(systemName: buttonIcon).productLinkBlockImage()
                Text(buttonText).productLinkBlockText()
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(Color(buttonColor))
        })
        .sheet(isPresented: $sheetActiveBool, onDismiss: dismissFunction) {
            fetchView()
        }
        
    }
    
    
    @ViewBuilder
    func fetchView() -> some View {
         buttonView
    }
}

struct ProductsTabButton_Previews: PreviewProvider {
    static var previews: some View {
        ProductsTabButton(
            dismissFunction: {
                print("Test")
            },
            buttonColor: "rmYellow",
            buttonText: "Yellow",
            buttonIcon: "list.star",
            //buttonView: SearchView()
            buttonView: Text("Test")
        )
    }
}

Any help with this would be greatly appreciated.

Thank you!

答案1

得分: 1

不应该将View作为View的属性。如果它是更大视图的可定制部分,请存储一个返回视图的闭包。

struct ProductsTabButton<ButtonView: View>: View {
    
    @State var sheetActiveBool: Bool = false
    var dismissFunction: () -> Void
    var buttonColor: String
    var buttonText: String
    var buttonIcon: String
    var buttonView: () -> ButtonView

    // ...
}

您可以直接将此闭包传递给sheet

.sheet(isPresented: $sheetActiveBool, onDismiss: dismissFunction, content: buttonView)

如果要为此属性设置默认值,请在扩展中编写初始化程序:

struct ProductsTabButton<ButtonView: View>: View {
    
    // ...

    init(buttonColor: String = "rmWhite", buttonText: String = "Button Text", buttonIcon: String = "list.dash", @ViewBuilder buttonView: @escaping () -> ButtonView, dismiss: @escaping () -> Void) {
        self.buttonColor = buttonColor
        self.buttonIcon = buttonIcon
        self.dismissFunction = dismiss
        self.buttonText = buttonText
        self.buttonView = buttonView
    }

    // ...
}

extension ProductsTabButton where ButtonView == BackgroundView {
    init(buttonColor: String = "rmWhite", buttonText: String = "Button Text", buttonIcon: String = "list.dash", dismiss: @escaping () -> Void) {
        self.init(buttonColor: buttonColor, buttonText: buttonText, buttonIcon: buttonIcon, buttonView: { BackgroundView() }, dismiss: dismiss)
    }
}
英文:

You should not have Views as properties of Views. If it's a customisable part of a bigger view, store a closure that returns a view instead.

struct ProductsTabButton<ButtonView: View>: View {
    
    @State var sheetActiveBool: Bool = false
    var dismissFunction: () -> Void
    var buttonColor: String
    var buttonText: String
    var buttonIcon: String
    var buttonView: () -> ButtonView

    // ...
}

You can pass this closure to sheet directly:

.sheet(isPresented: $sheetActiveBool, onDismiss: dismissFunction, content: buttonView)

If you want a default value for this property, write an initialiser in an extension:

struct ProductsTabButton<ButtonView: View>: View {
    
    // ...

    init(buttonColor: String = "rmWhite", buttonText: String = "Button Text", buttonIcon: String = "list.dash", @ViewBuilder buttonView: @escaping () -> ButtonView, dismiss: @escaping () -> Void) {
        self.buttonColor = buttonColor
        self.buttonIcon = buttonIcon
        self.dismissFunction = dismiss
        self.buttonText = buttonText
        self.buttonView = buttonView
    }

    // ...
}

extension ProductsTabButton where ButtonView == BackgroundView {
    init(buttonColor: String = "rmWhite", buttonText: String = "Button Text", buttonIcon: String = "list.dash", dismiss: @escaping () -> Void) {
        self.init(buttonColor: buttonColor, buttonText: buttonText, buttonIcon: buttonIcon, buttonView: { BackgroundView() }, dismiss: dismiss)
    }
}

huangapple
  • 本文由 发表于 2023年7月4日 21:27:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76613146.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定