You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从NotificationsEnum类型数组中移除指定userId的通知

问题描述

我的ProfileViewModel里有一个NotificationsEnum类型的通知数组,用来根据后端推送的不同通知类型(比如点赞、评论)展示对应的SwiftUI视图。现在需要移除数组中所有userId匹配指定值的通知,但userId属性没法直接从NotificationsEnum访问。

通知结构打印示例:

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

相关代码如下:

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 }
           // 需要实现类似下面的逻辑...
           // 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
}

解决方案

这里提供两种可行的实现方式,按需选择:

方案一:给Enum添加统一的userId计算属性(推荐)

给NotificationsEnum新增一个计算属性,统一返回不同case下的userId,后续所有需要获取用户ID的场景都能复用:

修改后的NotificationsEnum代码:

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

    // 新增:统一获取userId的计算属性
    var userId: String {
        switch self {
            case .like(let like):
                return like.userId
            case .comment(let comment):
                return comment.userId
        }
    }

    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
        }
    }
}

然后在ProfileViewModel中直接使用该属性完成过滤:

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 }
            // 直接用新增的userId属性过滤
            self.notifications.removeAll(where: { $0.userId == userId })
        }.store(in: &subscriptions)
    }
}

方案二:直接在过滤闭包中判断Enum case(无需修改Enum)

如果不想改动Enum的结构,可以在removeAll(where:)的闭包内通过switch逐个判断case:

修改后的ProfileViewModel代码:

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 }
            self.notifications.removeAll { notification in
                switch notification {
                case .like(let like):
                    return like.userId == userId
                case .comment(let comment):
                    return comment.userId == userId
                }
            }
        }.store(in: &subscriptions)
    }
}

方案对比

  • 方案一:代码更简洁,复用性强,适合长期维护的场景。
  • 方案二:无需修改原有Enum结构,但代码冗余,仅适合临时需求。

内容的提问来源于stack exchange,提问作者kissues

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 14:24:17