Кэширование в Swift: Redis, Memcached и встроенные решения для iOS/macOS

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Кэширование в Swift: Redis, Memcached и встроенные решения

Кэширование — один из ключевых инструментов для повышения производительности и отзывчивости приложений на Swift для iOS и macOS. В этой статье мы разберем три основных подхода: встроенные решения (NSCache, URLCache), а также внешние системы (Redis и Memcached). Вы узнаете, когда и какой инструмент выбрать, и получите готовые примеры кода.

Зачем нужно кэширование в Swift-приложениях?

Без кэширования каждое обращение к данным (сеть, диск, база данных) загружает систему и увеличивает время отклика. Кэш позволяет хранить часто используемые данные в оперативной памяти, сокращая задержки и нагрузку на сервер. Для мобильных устройств это особенно важно: экономия трафика, батареи и улучшение UX.

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

// Настройка URLCache
let memoryCapacity = 50 * 1024 * 1024 // 50 MB
let diskCapacity = 100 * 1024 * 1024 // 100 MB
let cache = URLCache(memoryCapacity: memoryCapacity, diskCapacity: diskCapacity, diskPath: "myCache")

let configuration = URLSessionConfiguration.default
configuration.urlCache = cache
configuration.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 RediStack
import NIOCore
import NIOPosix

// Подключение к Redis
let 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()

Redis поддерживает TTL (время жизни ключа), что полезно для кэша:

try connection.setex("temp:data", to: "some_value", expirationInSeconds: 3600).wait()

3. Memcached для Swift: распределенный кэш

Memcached — еще одна популярная система кэширования, проще Redis, но с меньшим функционалом. Для Swift используйте библиотеку MemcachedKit или Perfect-Memcached.

Пример с MemcachedKit

import MemcachedKit

// Подключение
let memcached = try Memcached(hostname: "localhost", port: 11211)

// Установка значения (с TTL 120 секунд)
try memcached.set("session:abc123", value: "user_data", expiration: 120)

// Получение значения
if let value: String = try memcached.get("session:abc123") {
    print("Из Memcached: \(value)")
}

// Удаление
try memcached.delete("session:abc123")

Memcached идеален для простого кэширования сессий, API-ответов или результатов вычислений, где не нужна сложная структура данных.

Сравнение: когда что использовать?

Критерий NSCache / URLCache Redis Memcached
Область применения Локальное кэширование на устройстве Серверное / распределенное кэширование Серверное / распределенное кэширование
Сложность Низкая (встроено в iOS/macOS) Средняя (требуется установка сервера) Низкая (простой протокол)
Поддержка TTL Нет (только ручное управление) Да (EXPIRE, SETEX) Да (expiration)

Блоги

Рекомендаций по книгам