Доступ к NSCache через контроллеры представления в контроллере представления с вкладками - PullRequest
1 голос
/ 02 апреля 2019

Я хочу получить доступ к NSCache из более чем одного места в моем приложении, поскольку я использую его для кэширования изображений с конечной точки API.

Например, в табличном представлении 4 и viewcontroller 6 на диаграмме ниже используются одни и те же изображения, поэтому я не хочу загружать их дважды.

enter image description here

Возможные решения:

  1. Singleton

    class Cache {  
    
        private static var sharedCache: NSCache<AnyObject, AnyObject>?        
        static public func getCache () -> NSCache<AnyObject, AnyObject> {
    
            if sharedCache == nil {
                self.sharedCache = NSCache()
            }
            return sharedCache!
        } 
    }
    

Кажется, работает нормально, но "Одиночки плохие", так что ...

  1. Хранить кеш в TabViewController

Это будет тесно связывать представления с контроллером представления, так что ...

  1. Хранить в AppDelegate как-нибудь. Но разве это не то же самое, что 1? Итак ...

  2. Использовать внедрение зависимостей. Но мы находимся в контроллере представления вкладок, так что это не то же самое, что 2?

Я не уверен, что здесь правильная стратегия, поэтому спрашиваю, есть ли другой метод, который можно использовать здесь.

Что я сделал Создал приложение с примером, использующим NSCache, и исследовал одноэлементное решение. Я пытался использовать внедрение зависимостей, но думаю, что это не имеет смысла. Я посмотрел на переполнение стека и документацию, но для этого конкретного обстоятельства я не нашел потенциальных растворенных веществ.

То, что я дал Минимальный пример с диаграммой и проверенным решением, которым я недоволен.

Что не полезно - это ответы, в которых говорится, что NSCache неверен, или использование библиотек. Я пытаюсь использовать NSCache для собственного обучения, это не домашняя работа, и я хочу решить этот конкретный случай этой проблемы в этой структуре приложения.

В чем вопрос Как избежать использования синглтона в этом случае, просматривать контроллеры в контроллере представления вкладок.

1 Ответ

2 голосов
/ 02 апреля 2019

Сначала. Синглтоны не плохо по своей природе. Они могут затруднить тестирование вашего кода, и они действуют как магниты зависимости.

Синглтоны хороши для классов, которые являются инструментами, например, NSFileManager aka FileManger, то есть что-то, что не несет состояния или данных.

Хорошей альтернативой является внедрение зависимостей, но с контроллерами представления и раскадровками это может быть сложно и чувствовать себя очень стандартно. В конечном итоге вы передаете все по линии в prepareForSegue.

Один из возможных способов - объявить protocol, описывающий кеш-подобный интерфейс.

protocol CacheProtocol: class {
    func doCacheThing()
}

class Cache: CacheProtocol {
    func doCacheThing() {
        //
    }
}

Затем объявите protocol, что могут использовать все вещи, которые хотят использовать этот кеш.

protocol CacheConsumer: class {
    var cache: CacheProtocol? { get set }
    func injectCache(to object: AnyObject)
}

extension CacheConsumer {
    func injectCache(to object: AnyObject) {
        if let consumer = object as? CacheConsumer {
            consumer.cache = cache
        }
    }
}

Наконец, создайте конкретный экземпляр этого кэша на верхнем уровне.

/// Top most controller
class RootLevelViewController: UIViewController, CacheConsumer {
    var cache: CacheProtocol? = Cache()

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        injectCache(to: segue.destination)
    }

}

Вы можете передать кеш в строку prepareForSegue.

Или вы можете использовать тонкие подклассы для создания соответствия.

class MyTabBarController: UITabBarController, CacheConsumer {
    var cache: CacheProtocol?
}

Или вы можете использовать методы делегата, чтобы транслировать объект кеша вниз.

extension RootLevelViewController: UITabBarControllerDelegate {
    func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
        injectCache(to: viewController)
    }
}

Теперь у вас есть система, в которой любой CacheConsumer может использовать кеш и передавать его под уклон любому другому объекту.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...