التخزين المؤقت في Swift: Redis وMemcached والحلول المضمنة
التخزين المؤقت هو أحد الأدوات الرئيسية لتحسين أداء واستجابة تطبيقات Swift لنظامي iOS وmacOS. في هذه المقالة، سنحلل ثلاثة أساليب رئيسية: الحلول المضمنة (NSCache, URLCache)، بالإضافة إلى الأنظمة الخارجية (Redis وMemcached). ستتعرف على متى وأي أداة تختار، وستحصل على أمثلة جاهزة للكود.
لماذا نحتاج التخزين المؤقت في تطبيقات Swift؟
بدون التخزين المؤقت، كل وصول إلى البيانات (الشبكة، القرص، قاعدة البيانات) يحمّل النظام ويزيد من وقت الاستجابة. يسمح التخزين المؤقت بتخزين البيانات المستخدمة بشكل متكرر في الذاكرة العشوائية، مما يقلل من التأخير والضغط على الخادم. بالنسبة للأجهزة المحمولة، هذا مهم بشكل خاص: توفير في استهلاك البيانات، البطارية، وتحسين تجربة المستخدم.
1. الحلول المضمنة: NSCache وURLCache
توفر Apple أداتين مضمنتين قويتين: NSCache للتخزين المؤقت العام للكائنات وURLCache للتخزين المؤقت لطلبات الشبكة.
NSCache
NSCache هو مخبأ آمن للخيوط، يدير الذاكرة تلقائياً. يقوم بحذف الكائنات عند نقص الذاكرة، مما يجعله مثالياً لنظام iOS.
import Foundation
class ImageCacheManager { static let shared = ImageCacheManager() private let cache = NSCache<NSString, UIImage>() private init() { cache.countLimit = 100 // الحد الأقصى 100 صورة cache.totalCostLimit = 50 * 1024 * 1024 // 50 MB } func getImage(for key: String) -> UIImage? { return cache.object(forKey: key as NSString) } func setImage(_ image: UIImage, for key: String, cost: Int = 0) { cache.setObject(image, forKey: key as NSString, cost: cost) } func removeImage(for key: String) { cache.removeObject(forKey: key as NSString) } func clearCache() { cache.removeAllObjects() }}URLCache
URLCache يقوم بتخزين استجابات HTTP مؤقتاً بشكل تلقائي. يمكن تهيئته لجلسة URLSession محددة.
import Foundation
// إعداد URLCachelet memoryCapacity = 50 * 1024 * 1024 // 50 MBlet diskCapacity = 100 * 1024 * 1024 // 100 MBlet cache = URLCache(memoryCapacity: memoryCapacity, diskCapacity: diskCapacity, diskPath: "myCache")
let configuration = URLSessionConfiguration.defaultconfiguration.urlCache = cacheconfiguration.requestCachePolicy = .returnCacheDataElseLoad
let session = URLSession(configuration: configuration)
// مثال على طلبlet url = URL(string: "https://api.example.com/data")!let task = session.dataTask(with: url) { data, response, error in if let data = data { // قد تكون البيانات من المخبأ print("تم استلام \\(data.count) بايت") }}task.resume()2. Redis لـ Swift: التخزين المؤقت على جانب الخادم
Redis هي قاعدة بيانات في الذاكرة (in-memory)، تُستخدم غالباً للتخزين المؤقت على جانب الخادم. بالنسبة لـ Swift، توجد مكتبة شائعة Vapor Redis (لـ Vapor) أو RediStack (لأي مشاريع).
مثال مع RediStack
import RediStackimport NIOCoreimport NIOPosix
// الاتصال بـ Redislet eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)let connection = try RedisConnection.make( configuration: .init(hostname: "localhost", port: 6379), boundEventLoop: eventLoopGroup.next()).wait()
// تعيين قيمةtry connection.set("user:123", to: "{\\"name\\": \\"Alice\\", \\"age\\": 30}").wait()
// الحصول على قيمةlet result = try connection.get("user:123", as: String.self).wait()print("تم الحصول من Redis: \\(result ?? "nil")")
// إغلاق الاتصالtry connection.close().wait()try eventLoopGroup.syncShutdownGracefully()