Swift中的缓存(iOS/macOS):Redis、NSCache和Core Data

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Swift中的缓存(iOS/macOS):从内存缓存到Redis



在iOS和macOS开发中,缓存是加速应用程序运行、降低服务器负载和改善用户体验的关键工具。在本文中,我们将探讨Swift中主要的缓存方法:从简单的NSCache到基于Redis和SQLite的专业解决方案。每种方法都有其适用场景,正确选择取决于数据类型、数据量以及持久性要求。



1. NSCache — 内置内存缓存



NSCache是一个轻量级、线程安全的缓存,内置于Foundation框架中。它会在资源不足时自动释放内存,因此非常适合缓存图像、API数据和其他临时对象。



import Foundation

class ImageCache { private let cache = NSCache<NSString, UIImage>() func getImage(forKey key: String) -> UIImage? { return cache.object(forKey: key as NSString) } func setImage(_ image: UIImage, forKey key: String) { cache.setObject(image, forKey: key as NSString) } func removeImage(forKey key: String) { cache.removeObject(forKey: key as NSString) }}


优点:

  • 无需配置 — 开箱即用。
  • 自动管理内存(在didReceiveMemoryWarning时删除对象)。
  • 线程安全。


缺点:

  • 应用程序重启后数据丢失。
  • 不适合大量数据(受限于RAM)。


2. Core Data作为持久化缓存



Core Data不仅常用作ORM,还可用作结构化数据的缓存。当需要保存带有关系的复杂对象并执行过滤时,这非常方便。



import CoreData

class CoreDataCache { private let context: NSManagedObjectContext init(context: NSManagedObjectContext) { self.context = context } func cacheResponse(_ data: Data, forKey key: String) { let cached = CachedResponse(context: context) cached.key = key cached.data = data cached.timestamp = Date() try? context.save() } func getCachedResponse(forKey key: String) -> Data? { let fetchRequest: NSFetchRequest<CachedResponse> = CachedResponse.fetchRequest() fetchRequest.predicate = NSPredicate(format: "key == %@", key) fetchRequest.sortDescriptors = [NSSortDescriptor(key: "timestamp", ascending: false)] fetchRequest.fetchLimit = 1 guard let result = try? context.fetch(fetchRequest).first else { return nil } return result.data }}


使用场景:

  • 数据需要在会话之间持久保存。
  • 需要复杂的过滤(例如,文本搜索)。
  • 数据量适中(最多几十万条记录)。


3. Redis — Swift的服务器端缓存



Redis是一个高性能的内存存储,通过网络运行。在Swift(iOS/macOS)的上下文中,Redis通常用于服务器端(Vapor、Kitura)来缓存会话、复杂查询结果和任务队列。然而,也有一些客户端库允许从移动应用程序直接连接到Redis(例如,通过RediStack)。



import RediStack

final class RedisCache { private let connection: RedisConnection init(host: String, port: Int = 6379) async throws { self.connection = try await RedisConnection.connect( to: .init(hostname: host, port: port) ) }

推荐