SwiftUI ForEach“无法推断复杂的闭包返回类型;添加显式类型以消除歧义”

Posted

技术标签:

【中文标题】SwiftUI ForEach“无法推断复杂的闭包返回类型;添加显式类型以消除歧义”【英文标题】:SwiftUI ForEach "Unable to infer complex closure return type; add explicit type to disambiguate" 【发布时间】:2019-09-20 20:33:32 【问题描述】:

我已经被困在这个问题上好几天了,现在试图找出问题所在。

我已经构建了一个视图,其中列出了我可以使用核心数据放入和保存的数据。

我的数据模型看起来像这样

我可以将数据添加到列表中并将其全部读回而没有任何问题,但是当我尝试过滤获取的结果时,我得到了标题中的错误。错误大约是代码的一半。
import CoreData


struct CollectionRow: View 
    var collectionDate = Date()
    let dateFormatter = DateFormatter()
    var body: some View 
        dateFormatter.dateStyle = .short
        dateFormatter.locale = Locale(identifier: "en_GB")
            return Text(dateFormatter.string(from: collectionDate))
    


struct CollectionList: View 

    var hospital = Hospital()

    @Environment(\.managedObjectContext) var managedObjectContext

    @FetchRequest(
        entity: Collection.entity(),
        sortDescriptors: [
            NSSortDescriptor(keyPath: \Collection.date, ascending: true)
        ]
    ) var collections: FetchedResults<Collection>

    @State private var collectionName = ""


    var body: some View 
        NavigationView 
            List 
                VStack 
                    ForEach(collections, id: \.self)  collection in //Unable to infer complex closure return type; add explicit type to disambiguate
                        if self.hospital.id == collection.hospital 
                            NavigationLink(destination: CollectionRow(collectionDate: Date()))
                                CollectionRow(collectionDate: Date())
                            
                        
                    
                    TextField("Test", text: $collectionName)
                    Button(action: 
                        let col = Collection(context: self.managedObjectContext)
                        col.date = Date()
                        col.id = Int16(self.collections.endIndex + 1)
                        col.hospital = self.hospital.id

                        self.hospital.addToHospToCol(col)

                        do 
                            try self.managedObjectContext.save()
                         catch 
                            print(error)
                        

                        self.collectionName = ""
                    ) 
                        Text("New Collection")
                    
                
            
            .navigationBarTitle(Text((hospital.name ?? "") + " - " + String(hospital.id)))
        
    

编辑:官方教程在 ForEach 中使用了 if 语句,那我为什么不能呢?

ForEach(landmarkData)  landmark in
                    if !self.showFavoritesOnly || landmark.isFavorite 
                        NavigationLink(destination: LandmarkDetail(landmark: landmark)) 
                            LandmarkRow(landmark: landmark)
                        
                    
                

【问题讨论】:

How can I filter an array in SwiftUI?的可能重复 SwiftUI 中的错误消息往往有点随机。我的建议是注释掉你的代码,直到你得到一个有意义的错误。我的直觉是你应该让 Collection 符合 Identifiable 然后声明 ForEach(collections) 再看一遍,错的是整个 ForEach。 SwiftUI 中的 ForEach 不是你从集合中知道的 forEach。在 SwiftUI 中,它用于构造列表,而我认为您正在使用它来过滤掉一个元素。我对吗?您是否尝试仅针对具有匹配 ID 的医院显示一个链接? 不是一个,只有匹配的。官方教程在 ForEach 中使用 if 语句来过滤结果 【参考方案1】:

SwiftUI 中的if/else 只能在@ViewBuilder 闭包内使用,因此ForEach 失败。

更多关于函数构建器here。

一个简单的解决方案是像这样包装你的代码:

struct ForEachBuilder<Content>: View where Content: View 

    private let content: Content

    init(@ViewBuilder content: () -> Content) 
        self.content = content()
    

    var body: some View 
        content
    


你的ForEach 会变成:

ForEach(collections, id: \.self)  collection in 
    ForEachBuilder 
        if self.hospital.id == collection.hospital 
            // Your navigation link
        
    

【讨论】:

if if/else 语句只能在@ViewBuilder 语句中使用,官方教程怎么能和我一样使用if语句? @Shuttleu 你能发个教程的链接吗? developer.apple.com/tutorials/swiftui/handling-user-input 第 5 节,第 3 步 同样的问题。在本教程中可能没有使用 CoreData。但实际上这不应该是一个原因。

以上是关于SwiftUI ForEach“无法推断复杂的闭包返回类型;添加显式类型以消除歧义”的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 SwiftUI 推断复杂的闭包返回类型

SwiftUI 如何修复“无法推断复杂的闭包返回类型;添加显式类型以消除歧义”

SwiftUI ForEach-Loop 出现错误

Swift Combine:无法推断复杂的闭包返回类型错误

无法推断复杂的闭包返回类型;添加显式类型以消除歧义

在 VStack 中包装 WebView 时出错:无法推断复杂的闭包返回类型;添加显式类型以消除歧义