Xcode Beta 6“表达式类型在没有更多上下文的情况下是含糊的” Navigationlink

时间:2019-08-20 19:57:05

标签: swift xcode swiftui

自从今天早些时候更新到Xcode Beta 6之后,我的应用程序将不再构建,因此在Beta 5及更早版本中可以正常工作。

这是带有错误消息的文件中的代码,尽管我现在知道这并不一定意味着这是错误所在。

import SwiftUI

struct JobView_Table : View {

    @ObservedObject var jobList: JobDetailViewModel = JobDetailViewModel()

    var body: some View {

        NavigationView {

            List {
                ForEach($jobList.jobDetails) { job in
                    NavigationLink(destination: JobDetailHost(jobDetails: job)) { // ERROR: "Type of expression is ambiguous without more context"
                        JobView_List(jobDetails: job)
                    }
                }
            }

            .navigationBarTitle(Text("My Jobs"))
            .onAppear(perform: fetchData)
            .onAppear(perform: {
                print("Hello!")
            })

        }
    }

    private func fetchData() {
        return(jobList.updateDetails())
    }
}

包含数据的结构正确符合以下协议。

struct JobDetails: Codable, Identifiable, Equatable, Hashable { 
    ...

    ...
}

这是向JobView_Table提供数据的类。

import Foundation
import UIKit
import Combine

class JobDetailViewModel: ObservableObject, Identifiable {

    @Published var jobDetails: [JobDetails] = []

    func updateDetails() {
        self.jobDetails = DataManager().fetchJobList()
    }

}

最后是通过NavigationLink链接到的目标视图。

struct JobDetailHost: View {

    @Environment(\.editMode) var mode
    @Binding var jobDetails: JobDetails


    var body: some View {

        VStack {
            JobDetailView(jobDetails: jobDetails)
        }
        .navigationBarItems(trailing: EditButton())
    }

}

我注意到其他一些人似乎也有类似的问题,即在下面列出的两个问题中,但是目前无法找到这些问题的答案。 SwiftUI Xcode 11 beta 5 / 6: Type of expression is ambiguous without more context

SwiftUI: Why does ForEach($strings) (text: Binding) not build?

编辑:

我尝试执行Fabian的建议,这消除了错误,但是列表中没有内容。

这是经过调整的List代码,可以成功编译,但是在运行应用程序时未填充列表。

List {
    ForEach(jobList.jobDetails.indexed(), id: \.1.id) { (index, job) in
            NavigationLink(destination: JobDetailHost(jobDetails: self.$jobList.jobDetails[index])) {
                        Text(job.jobName)
                    }
     }
}

以下内容不使用ForEach并丢弃NavigationLink,仍然不起作用。

List(jobList.jobDetails.indexed(), id: \.1.id) { (index, job) in
                Text(job.jobName)
            }

1 个答案:

答案 0 :(得分:4)

我将引用macOS Catalina 10.15 Beta 6 Release Notes

  

绑定结构对集合的条件一致性   协议已删除。 (51624798)

     

如果您具有以下代码:

struct LandmarkList: View {
    @Binding var landmark: [Landmark]

    var body: some View {
        List(landmarks) { landmark in
            Toggle(landmark.value.name, isOn: landmark[\.isFavorite])
        }
    }
}
     

定义以下收集类型:

struct IndexedCollection<Base: RandomAccessCollection>: RandomAccessCollection {
    typealias Index = Base.Index
    typealias Element = (index: Index, element: Base.Element)

    let base: Base

    var startIndex: Index { base.startIndex }

    var endIndex: Index { base.endIndex }

    func index(after i: Index) -> Index {
        base.index(after: i)
    }

    func index(before i: Index) -> Index {
        base.index(before: i)
    }

    func index(_ i: Index, offsetBy distance: Int) -> Index {
        base.index(i, offsetBy: distance)
    }

    subscript(position: Index) -> Element {
        (index: position, element: base[position])
    }
}

extension RandomAccessCollection {
    func indexed() -> IndexedCollection<Self> {
        IndexedCollection(base: self)
    }
}
     

然后,将代码更新为:

struct LandmarkList: View {
    @Binding var landmarks: [Landmark]

    var body: some View { // Does often give error on id: \.1.id
        List(landmarks.indexed(), id: \.1.id) { (index, landmark) in
            Toggle(landmark.name, isOn: self.$landmarks[index].isFavorite)
        }
    }
}

您的代码还将Binding<[JobDetails]>$jobList.jobDetails一起使用,但是Binding<[JobDetails]>不再符合收集协议。

但是请注意上面的解决方案,由于编译器无法理解\.1.id引用了元组\.1定义的第二个元素,因此我无法识别IndexedCollection ,但可能是我用错了。可以重写它,但这使它起作用。

使用IndexedCollection的示例

struct AnotherIndexedView_NeedsEnv: View {
    @EnvironmentObject var modalManager: ModalManager

    var body: some View {
        ZStack {
            SwiftUI.ForEach(modalManager.modals.indexed()) { m in
                ModalView(currentModal: self.$modalManager.modals[m.index]).environmentObject(self.modalManager)
            }
        }.onAppear(perform: {self.modalManager.fetchContent()})
    }
}