Home > Mobile >  How to remove objects in Enum type array?
How to remove objects in Enum type array?

Time:07-30

I have an array of notifications in my view model that are of type NotificationsEnum so that I can send different types of notifications from my backend and display them in their matching SwiftUI view depending on their type. (like, comment, etc...)

NotificationEnum data type is used to switch on the notification's type property so I can assign it to its appropriate View.

I want the ability to remove all notifications from ProfileViewModel's notifications array that are have the same userId.

The problem I am having is figuring out how to remove these notifications from the ProfileViewModels notifications array (of type [NotificationsEnum]) by userId when the userId property is not directly accessed from type NotificationsEnum and is "obscured away".

If I print out each notification, you can see their structure below:

[
    App.NotificationsEnum.like (
      App.LikeNotification(id: "62ed8df9fd9df47c", type: "like", userId: 
        "634k32816fjh35sd35182d3", )
   )
]

How can I write code that will remove all notifications where: { userId == userId } inside of my ProfileViewModel's static subscription removeNotifications??

Thank you!

VIEW MODEL

class ProfileViewModel: ObservableObject {
    
    @Published var notifications: [NotificationsEnum] = []
    
    var subscriptions = Set<AnyCancellable>()
    static let removeNotifications = PassthroughSubject<String, Never>()
    
    init() {
        Self.removeNotifications.sink { [weak self] userId in
            guard let self = self else { return }
           // Need code that functions like below example...
           // self.notifications.removeAll(where: {$0.userId == userId})
        }.store(in: &subscriptions)
    }
}

NOTIFICATION ENUM TYPE

enum NotificationsEnum: Decodable, Identifiable {
    
    var id: String {
        switch self {
            case .like(let like):
                return like.id
            case .comment(let comment):
                return comment.id
       
            }
    }

    case like(LikeNotification)
    case comment(CommentNotification)
 
        
    private enum CodingKeys: String, CodingKey {
        case type
    }
    
   init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
    
    let type = try container.decode(String.self, forKey: .type)
        switch type {
        case "like":
            self = try .like(LikeNotification(from: decoder))
        case "comment":
            self = try .comment(CommentNotification(from: decoder))
        default:
             throw DecodingError.wrongJSON
        }
    }
}

LIKE & COMMENT NOTIFICATION MODELS

struct CommentNotification: Codable, Identifiable {
    let id: String
    let type: String
    let userId: String
    let comment: String
}

struct LikeNotification: Codable, Identifiable {
    let id: String
    let type: String
    let userId: String
}

CodePudding user response:

You can add an extension to your NotificationsEnum that exposes the userId property:

extension NotificationsEnum {
    var userId : String {
        switch self {
        case .like(let like):
            return like.userId
        case .comment(let comment):
            return comment.userId
        }
    }
}

Then:

self.notifications.removeAll { $0.userId == userId }

Alternatively, you could do the switch within the removeAll if you didn't have the extension, but the first solution seems cleaner.

  • Related