Reputation: 2781
My goal here is to make a SwiftUI struct which makes a scrolling view of data in a sequence, where the data, and the data_view get put together inside the ScrollView.
I get the title error from this code on the ForEach line. The type of the array doesn't seem to matter, I set it to 'Any', and got the same error.
import SwiftUI
protocol DatedOrPrioritizedStruct {
var id: UUID {get}
var priority: Float {get set} ///Priority must be set
var start: Date? {get set} ///Could be nil. Used in conjunction with priority if set.
}
struct TimeLine : View {
var data: [DatedOrPrioritizedStruct]
var body: some View {
GeometryReader { geometry in
NavigationView {
VStack {
ScrollView {
ForEach(self.data, id: \.self) { item in
//^-ERROR redline here
TaskView(task: item).frame(minWidth: 0, idealWidth: geometry.size.width * 0.80, maxWidth: geometry.size.width, alignment: .leading)
}
}.frame(minWidth: 0, maxWidth: geometry.size.width, alignment: .leading)
.navigationBarTitle("Do The First Thing", displayMode: .large)
}
}.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
}
}
}
The Task class:
public class Task: DatedOrPrioritizedStruct, Identifiable, Equatable {
public static func == (lhs: Task, rhs: Task) -> Bool {
return lhs.id == rhs.id
}
public let id = UUID()
var title: String
var creation: Date
var priority: Float
var start: Date?
var deadline: Date?
var completed: Date?
var note: String?
var recur: Double?
var duration: TimeInterval
public init (_ title: String) {
self.title = title
self.creation = Date()
self.priority = 3.0
self.start = nil
self.deadline = nil
self.completed = nil
self.note = nil
self.recur = nil
self.duration = 3600.0
}
public init (_ title: String, priority: Float) {
self.title = title
self.creation = Date()
self.priority = priority
self.start = nil
self.deadline = nil
self.completed = nil
self.note = nil
self.recur = nil
self.duration = TimeInterval(9 * 24 * 3600 + 3 * 3600 + 20 * 60)
}
}
Upvotes: 0
Views: 2511
Reputation: 8106
If you replace the
TaskView(task: item).frame(minWidth: 0, idealWidth: geometry.size.width * 0.80, maxWidth: geometry.size.width, alignment: .leading)
line with a simple Text("Testing")
, you'll see the error change to
Protocol type 'DatedOrPrioritizedStruct' cannot conform to 'Hashable' because only concrete types can conform to protocols
You can fix this by specifying the ForEach
's identifier to be \.id
:
ForEach(self.data, id: \.id) { item in
TaskView(task: item).frame(minWidth: 0, idealWidth: geometry.size.width * 0.80, maxWidth: geometry.size.width, alignment: .leading)
}
Make sure that TaskView
's task
is of type DatedOrPrioritizedStruct
, not Task
, because since your data
array contains DataOrPrioritizedStruct
objects, the item
in the ForEach
will be a DataOrPrioritizedStruct
, not a Task
.
Side note: Currently, Xcode often gives irrelevant errors, like in this case, and you can try to figure out the true source by simplifying your code (which I did by putting Text("Testing")
in the ForEach
and commenting out the TaskView
line).
Edit:
To clarify, TaskView
expects to receive Task
type, but the ForEach
iterates on an array of DataOrPrioritizedStruct
, so when you pass item
into TaskView
there is no guarantee that the object has the data members that are unique to Task
, which is why TaskView
's task
's type must be DataOrPrioritizedStruct
, not Task
.
Upvotes: 1