Swift NSCache Singleton

Aug 31 2020

Chcę opakować NSCache w Singleton, aby użyć iniekcji zależności w moim kodzie. Spowodowało to, niestety, przekazanie typu przez parametr funkcji, a nawet potrzebuję dwóch makiet dla sukcesu i niepowodzenia, ponieważ jest to instancja pojedyncza.

Myślę, że może być lepszy sposób, ale wszelkie komentarze są mile widziane!

ImageCache i protokół

protocol ImageCacheProtocol {
    static var shared: Self { get }
    func getCache() -> NSCache<AnyObject, UIImage>
}

final class ImageCache: ImageCacheProtocol {
    var cache: NSCache<AnyObject, UIImage> = NSCache<AnyObject, UIImage>()

    public static let shared = ImageCache()
    private init() {}
    
    func getCache() -> NSCache<AnyObject, UIImage> {
        return cache
    }
}

MockImageCache i MockImageCacheFailure

final class MockImageCache: ImageCacheProtocol {
    var cache: NSCache<AnyObject, UIImage> = MockNSCache(shouldReturnImage: true)

    public static let shared = MockImageCache()
    private init() {}

    func getCache() -> NSCache<AnyObject, UIImage> {
        return cache
    }
}


final class MockImageCacheFailure: ImageCacheProtocol {
    var cache: NSCache<AnyObject, UIImage> = MockNSCache(shouldReturnImage: false)

    public static let shared = MockImageCacheFailure()
    private init() {}

    func getCache() -> NSCache<AnyObject, UIImage> {
        return cache
    }
}

Tworzenie instancji mojego modelu widoku (fragment)

class ViewModel<U: ImageCacheProtocol> {

    private var cache: U.Type
    init<T: NetworkManagerProtocol>(networkManager: T, data: DisplayContent, imageCache: U.Type) {
        self.networkManager = AnyNetworkManager(manager: networkManager)
        
        cache = imageCache

Odpowiedzi

WishIHadThreeGuns Sep 02 2020 at 14:29

Tak, to nie jest kanoniczny sposób. Moje rozwiązanie to nie używać Selfi zamiast tego skupić się na udostępnianiu.

To jest:

protocol ImageCacheProtocol {
    func getCache() -> NSCache<AnyObject, UIImage>
}

final class ImageCache: ImageCacheProtocol {
    var cache: NSCache<AnyObject, UIImage> = NSCache<AnyObject, UIImage>()
    static var shared = ImageCache()
    
    private init() {}
    
    func getCache() -> NSCache<AnyObject, UIImage> {
        return cache
    }
}

Następnie można zmienić makiety:

final class MockImageCache: ImageCacheProtocol {
    var cache: NSCache<AnyObject, UIImage> = MockNSCache(shouldReturnImage: true)
    public static var shared: ImageCacheProtocol! = MockImageCache()
    func getCache() -> NSCache<AnyObject, UIImage> {
        return cache
    }
}