简体   繁体   English

Swift,无法将类型“() -> TupleView<(...)>”的值转换为预期的参数类型“() -> TupleView<(...)>”

[英]Swift, Cannot convert value of type '() -> TupleView<(...)>' to expected argument type '() -> TupleView<(...)>'

I'm trying to make an array of Views so that, ideally, each element of the array can have a different composition of child View elements.我正在尝试制作一个视图数组,以便理想情况下,数组的每个元素都可以具有不同的子视图元素组合。 I have tried to achieve this by creating an array of [some View] .我试图通过创建一个[some View]数组来实现这一点。 Apparently the compiler inspects the first element of the the array upon initializing the array and expects all elements have a similar composition of subviews.显然,编译器在初始化数组时检查数组的第一个元素,并期望所有元素都具有相似的子视图组合。 I'd appreciate any help to get around this problem or an alternative solution.对于解决此问题或替代解决方案的任何帮助,我将不胜感激。

In the simplest form I have created an array of [some View] with two VStack elements, yet each VStack contains two subviews, a Text and an Image with different layout order.在最简单的形式中,我创建了一个包含两个 VStack 元素的[some View]数组,但每个 VStack 包含两个子视图,一个 Text 和一个具有不同布局顺序的 Image 。

var myArray : [some View] = [
    VStack{
        Text("foo")
        Image("foo_image")
    },
    VStack{
        Image("bar_image")
        Text("bar")
    }
]

Apparently the compiler infers the type of array as () -> TuppleView<Text,Image> by evaluating the first element and complains that the second element is of type () -> TuppleView<Image,Text> can not be converted to the aforesaid type.显然,编译器通过评估第一个元素将数组类型推断为() -> TuppleView<Text,Image>并抱怨第二个元素的类型为() -> TuppleView<Image,Text>无法转换为上述类型类型。

My question is that whether there is a way to hide the detail of the containing Views or wrap it in an opaque object so that I can create an array of Views with different elements and layout arrangements.我的问题是,是否有办法隐藏包含视图的细节或将其包装在不透明的 object 中,以便我可以创建具有不同元素和布局安排的视图数组。

Here is a minimal reproducible example这是一个最小的可重现示例

struct WrapperView <Content : View> : View , Identifiable{
    var id: String
    let content : Content
    
    var body: some View{
        VStack{
            Text("Some text")
            content
        }
    }
    
    init(id : String , @ViewBuilder content : ()-> Content){
        self.id = id
        self.content = content()
    }
    
}

struct TheItemList {
    
    static var theItems : [WrapperView< some View>] = [
        WrapperView(id : "frist one" , content: {
            HStack{
                Text("foo")
                Image(systemName: "heart")
            }
        }),
        WrapperView(id : "second one" , content: {
            HStack{
                Image(systemName: "bolt")
                Text("bar")
            }
        })
    ]
}

struct TestView : View {
    
    var body: some View{
        ScrollView{
            ForEach(TheItemList.theItems , id: \.id){item in
                item
            }
        }
    }
}

struct TestView_Previews: PreviewProvider {
    
    static var previews: some View {
        TestView()
    }
}

Obviously everything is fine when the order of Text and Image elements in the second HStack matches the first one's.显然,当第二个 HStack 中的 Text 和 Image 元素的顺序与第一个相匹配时,一切都很好。

The way I would approach something like this...我处理这样的事情的方式......

You have an array of all sorts of different data.您有各种不同数据的数组。 Swift doesn't do heterogeneous arrays but we can get around this by creating an enum to hold the data... Swift 不做异构 arrays 但我们可以通过创建一个枚举来保存数据来解决这个问题......

enum ContentSection: Identifiable {
  case image(imageName: String)
  case text(String)
  case card(imageName: String, title: String)
  // other cases...

  var id: // put an id here
}

Then in the view you give it an array of these and use that to create the views.然后在视图中给它一个数组,并使用它来创建视图。

struct ContentView: View {
  let sections: [ContentSection] = ...

  var body: some View {
    VStack {
      ForEach(sections) { section in
        switch section {
          case .image(let imageName):
            Image(systemName: imageName)
          case .text(let text):
            Text(text)
          case let .card(imageName, title):
            MyCardView(imageName: imageName, title: title)
          // other cases...
        }
      }
    }
  }
}

This will create all your different views based on the type of the enum and the contents held inside each case.这将根据枚举的类型和每个案例中包含的内容创建所有不同的视图。

Problem Solved, Apparently wrapping the view items in AnyView can fix the problem, simple as that!问题已解决,显然将视图项包装在 AnyView 中可以解决问题,就这么简单!

var myArray : [some View] = [
    AnyView(VStack{
        Text("foo")
        Image("foo_image")
    }),
    AnyView(VStack{
        Image("bar_image")
        Text("bar")
    })
]

and this how it fixes the above mentioned example:以及它如何修复上述示例:

struct TheItemList  {
    
    static var theItems : [WrapperView< some View>] = [
        WrapperView(id : "frist one" , content: {
            AnyView( HStack{
                Image(systemName: "heart")
                Text("foo")
            })
        })
        ,
        WrapperView(id : "second one" , content: {
            AnyView(HStack{
                Text("bar")
                Image(systemName: "bolt")
            })
        })
    ]
    
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Swift 1.2到Swift 2:无法将类型的值转换为预期的参数类型 - Swift 1.2 to swift 2: Cannot convert value of type to expected argument type ios无法将类型“()”的值转换为预期的参数类型“字符串”,迅速3 - ios Cannot convert value of type '()' to expected argument type 'String' swift 3 无法在Swift 3中将字符串类型的值转换为预期的参数类型int - cannot convert value of type string to expected argument type int in swift 3 swift无法将类型(_,_)-&gt; _的值转换为预期的参数类型&#39;((_,CGFloat))-&gt; _ - swift cannot convert value of type (_, _) -> _ to expected argument type '((_, CGFloat)) -> _ 无法将“字符串”类型的值转换为预期的参数类型“ NSManagedObject” Swift - Cannot convert value of type 'String' to expected argument type 'NSManagedObject' Swift Swift 3.0无法将(_,_)-&gt;()类型的值转换为期望的参数类型&#39;ObjectsOrErrorBlock&#39; - Swift 3.0 cannot convert value of type (_, _)->() to Expected argument type 'ObjectsOrErrorBlock' swift:无法将类型“()”的值转换为预期的参数类型“ [Double]” - swift : Cannot convert value of type '()' to expected argument type '[Double]' Swift 无法将类型“()”的值转换为预期的参数类型“() -> Void” - Swift Cannot convert value of type '()' to expected argument type '() -> Void' Swift类别:“无法将类型的值转换为预期的参数类型&#39;AnyObject!&#39; - Swift category: "Cannot convert value of type to expected argument type 'AnyObject!' Swift:无法将类型&#39;() - &gt; Bool&#39;的值转换为预期的参数类型&#39;PFObject&#39; - Swift: Cannot convert value of type '() -> Bool' to expected argument type 'PFObject'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM