Xcode Beta 6 "Type of expression is ambiguous without more context" 导航链接
Xcode Beta 6 "Type of expression is ambiguous without more context" navigationlink
自从今天早些时候更新到 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 {
...
...
}
这是 class,它向 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: 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)
}
我将引用 macOS Catalina 10.15 Beta 6 Release Notes:
The Binding structure’s conditional conformance to the Collection
protocol is removed. (51624798)
If you have code such as the following:
struct LandmarkList: View {
@Binding var landmark: [Landmark]
var body: some View {
List(landmarks) { landmark in
Toggle(landmark.value.name, isOn: landmark[\.isFavorite])
}
}
}
Define the following collection type:
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)
}
}
Then, update your code to:
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]>
不再符合 Collection 协议。
但是请注意上面的解决方案,我遇到了无法识别 \.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()})
}
}
自从今天早些时候更新到 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 {
...
...
}
这是 class,它向 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: 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)
}
我将引用 macOS Catalina 10.15 Beta 6 Release Notes:
The Binding structure’s conditional conformance to the Collection protocol is removed. (51624798)
If you have code such as the following:
struct LandmarkList: View { @Binding var landmark: [Landmark] var body: some View { List(landmarks) { landmark in Toggle(landmark.value.name, isOn: landmark[\.isFavorite]) } } }
Define the following collection type:
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) } }
Then, update your code to:
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]>
不再符合 Collection 协议。
但是请注意上面的解决方案,我遇到了无法识别 \.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()})
}
}