I am getting the following error when I try to compare values in the task modifier.
Operator function '==' requires that 'Binding' conform to 'Equatable'
How can I make Binding confirm to Equatable? The non-binding ordinary NotificationDetail already confirms to Equatable.
@ObservedObject var notificationsViewModel = NotificationsViewModel.shared
//NotificationsViewModel does a API call and puts the fetched data in the Notifications Model
var body: some View {
VStack {
ForEach($notificationsViewModel.notifications.notificationsDetails) { $notificationsDetail in
VStack(alignment: .leading) {
if notificationsDetail.notificationsCategoriesId == 2 {
NotificationsFriendRequestCell(notificationsDetail: $notificationsDetail, viewModel: viewModel, notificationsViewModel: notificationsViewModel, tabSelection: $tabSelection) //ReceiveFriendRequestCell(user: user, viewModel: viewModel)
}
else if notificationsDetail.notificationsCategoriesId == 3 {
NotificationsFriendRequestApprovedCell(notificationsDetail: $notificationsDetail, viewModel: viewModel, notificationsViewModel: notificationsViewModel, tabSelection: $tabSelection)
}
}
.task { //task modifier for infinite scrolling
//BELOW LINE GETTING ERRROS
if $notificationsDetail == $notificationsViewModel.notifications.notificationsDetails.last {
print("task modifier last item")
numberOfSkips = 10
notificationsViewModel.getMyNotifications(isOnlyUnread: false, skip: numberOfSkips, limit: 10)
}
}
} //ForEach end
} //VStack end
Model
struct Notifications: Codable, Identifiable {
let id = UUID()
let numberOfNotifications: Int
var notificationsDetails: [NotificationsDetail]
enum CodingKeys: String, CodingKey {
case numberOfNotifications = "number_of_notifications"
case notificationsDetails = "notifications"
}
}
struct NotificationsDetail: Codable, Identifiable, Equatable {
let id: Int
let notificationsCategoriesId: Int
let questionsUsersName: String?
enum CodingKeys: String, CodingKey {
case id = "notifications_id"
case notificationsCategoriesId = "notifications_categories_id"
case questionsUsersName = "questions_users_name"
}
static var example = NotificationsDetail(id: 0, notificationsCategoriesId: 1, questionsId: 1, questionsUsersName: "")
init(id: Int, notificationsCategoriesId: Int, questionsUsersName: String?) {
self.id = id
self.notificationsCategoriesId = notificationsCategoriesId
self.questionsUsersName = questionsUsersName
}
}
ViewModel
class NotificationsViewModel: ObservableObject {
static let shared = NotificationsViewModel()
@Published var notifications: Notifications = Notifications.example
init(){
A()
}
func A () {
//do API calls and put data in @Published var notifications
}
I tried tweaking the values by removing or adding $ mark but get other errors...
if notificationsDetail == notificationsViewModel.notifications.notificationsDetails.last
//Error: Reference to captured var 'notificationsDetail' in concurrently-executing code
if $notificationsDetail == notificationsViewModel.notifications.notificationsDetails.last
//Error: Binary operator '==' cannot be applied to operands of type 'Binding<[NotificationsDetail]>.Element' (aka 'Binding<NotificationsDetail>') and '((NotificationsDetail) throws -> Bool) throws -> NotificationsDetail?'
Any advice would be highly appreciated! Thanks in advance.
CodePudding user response:
The reason for the error is you are handing your closure a binding through your ForEach
, but you want to compare to the value of this binding. Accessing it via $
and .wrappedValue
should work here. So change your code to:
if $notificationsDetail.wrappedValue == notificationsViewModel.notifications.notificationsDetails.last