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

单例模式优秀应用场景:点赞功能中的ENFeedLikeManager实现

我来帮你把这个点赞功能的单例管理类捋顺,结合你的需求给出完整的实现方案和注意细节:

单例ENFeedLikeManager完整实现

这个单例的核心作用是统一管理主页的点赞数据,同时对接推送通知的点赞事件,还要关联点赞列表的视图控制器来同步刷新UI。

1. 完整的单例代码实现

import UIKit

// 先定义点赞数据模型(如果你的项目里已有,可直接复用)
struct ENFeedLike: Codable {
    let userId: String
    let userName: String
    let avatarUrl: String?
    let likeTime: Date
}

// 点赞管理单例类
class ENFeedLikeManager: NSObject {
    // 全局唯一的单例实例,方便各处调用
    static let sharedInstance = ENFeedLikeManager()
    // 弱引用关联点赞列表视图控制器,避免循环引用
    weak var likeViewController: ENLikeViewController?
    // 存储所有点赞数据的数组,用private(set)保证外部只能读不能直接修改
    private(set) var likes = [ENFeedLike]()
    
    // 私有初始化方法,禁止外部创建新实例,确保单例唯一性
    private override init() {
        super.init()
        // 初始化时从本地加载之前保存的点赞数据,避免重启APP丢失
        loadLikesFromLocal()
    }
    
    // 处理推送通知时调用的添加点赞方法
    func addNewLike(_ like: ENFeedLike) {
        // 避免重复添加同一个用户的点赞(可根据业务需求调整判断逻辑)
        guard !likes.contains(where: { $0.userId == like.userId }) else {
            return
        }
        // 数组操作和UI相关操作必须在主线程执行,避免线程安全问题
        DispatchQueue.main.async { [weak self] in
            self?.likes.insert(like, at: 0) // 最新点赞放在数组最前面,符合列表展示逻辑
            self?.saveLikesToLocal() // 同步保存到本地
            // 如果点赞列表页面正在显示,直接触发UI刷新
            self?.likeViewController?.refreshLikeList()
        }
    }
    
    // 从本地加载点赞数据(用UserDefaults做轻量持久化,数据量大的话建议换CoreData/Realm)
    private func loadLikesFromLocal() {
        guard let data = UserDefaults.standard.data(forKey: "ENFeedLikes"),
              let savedLikes = try? JSONDecoder().decode([ENFeedLike].self, from: data) else {
            return
        }
        likes = savedLikes
    }
    
    // 将点赞数据保存到本地
    private func saveLikesToLocal() {
        guard let data = try? JSONEncoder().encode(likes) else {
            return
        }
        UserDefaults.standard.set(data, forKey: "ENFeedLikes")
        UserDefaults.standard.synchronize()
    }
}

// 定义点赞视图控制器的协议,规范刷新UI的方法
protocol ENLikeViewController: UIViewController {
    func refreshLikeList()
}

2. 关键细节说明

  • 单例安全性:通过private override init()禁止外部实例化,保证全局只有一个管理类实例,避免数据不一致。
  • 线程安全:所有修改likes数组和UI更新的操作都放在主线程,因为推送通知的回调大概率在后台线程执行,直接操作会有崩溃风险。
  • 数据持久化:加入了UserDefaults的存储逻辑,解决APP重启后点赞数据丢失的问题;如果你的点赞数据量较大,建议改用CoreData或Realm。
  • 避免重复点赞:添加了用户ID的判断逻辑,防止同一个用户的点赞被重复存入数组,你可以根据业务需求调整判断规则(比如允许同一用户多次点赞)。
  • UI联动:用弱引用关联likeViewController,新点赞到来时如果页面正在显示,直接触发刷新,比用通知中心更直接高效,还能避免不必要的监听。

3. 推送通知中的调用示例

当你收到点赞推送时,先从推送payload里解析出用户信息,创建ENFeedLike对象,再调用单例的添加方法:

// 假设从推送的userInfo中解析数据
guard let userId = userInfo["userId"] as? String,
      let userName = userInfo["userName"] as? String else {
    return
}
let avatarUrl = userInfo["avatarUrl"] as? String
let newLike = ENFeedLike(userId: userId, userName: userName, avatarUrl: avatarUrl, likeTime: Date())

// 调用单例添加点赞
ENFeedLikeManager.sharedInstance.addNewLike(newLike)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:53:54