我一直在尝试实现一个单例用作照片的缓存,我从网上上传到我的iOS应用程序.我在下面的代码中附加了三个变体.我试图让变量2工作,但它导致编译器错误,我不明白,并希望得到帮助我做错了什么.变体1执行缓存但我不喜欢使用全局变量.变体3没有进行实际的缓存,我相信这是因为我在var ic = ....的赋值中得到了一个副本,这是正确的吗?
任何反馈和见解将不胜感激.
谢谢,Zvi
import UIKit
private var imageCache: [String: UIImage?] = [String : UIImage?]()
class ImageCache {
class var imageCache: [String : UIImage?] {
struct Static {
static var instance: [String : UIImage?]?
static var token: dispatch_once_t = 0
}
dispatch_once(&Static.token) {
Static.instance = [String : UIImage?]()
}
return Static.instance!
}
}
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView.image = UIImage(data: NSData(contentsOfURL: NSURL(string: "http://images.apple.com/v/iphone-5s/gallery/a/images/download/photo_1.jpg")!)!)
//variant 1 - this code is working
imageCache["photo_1"] = imageView.image
NSLog(imageCache["photo_1"] == nil ? "no good" : "cached")
//variant 2 - causing a compiler error on next line: '@lvalue $T7' is not identical to '(String, UIImage?)'
//ImageCache.imageCache["photo_1"] = imageView.image
//NSLog(ImageCache.imageCache["photo_1"] == nil ? "no good" : "cached")
//variant 3 - not doing the caching
//var ic = ImageCache.imageCache
//ic["photo_1)"] = imageView.image
//NSLog(ImageCache.imageCache["photo_1"] == nil ? "no good" : "cached")
}
}
Run Code Online (Sandbox Code Playgroud)
Rob*_*Rob 30
标准单例模式是:
final class Manager {
static let shared = Manager()
private init() { ... }
func foo() { ... }
}
Run Code Online (Sandbox Code Playgroud)
而且你会这样使用它:
Manager.shared.foo()
Run Code Online (Sandbox Code Playgroud)
感谢appzYourLife指出应该声明它final
以确保它不会被意外地子类化以及使用private
初始化程序的访问修饰符,以确保您不会意外地实例化另一个实例.请参阅/sf/answers/2715562321/.
因此,返回到图像缓存问题,您将使用此单例模式:
final class ImageCache {
static let shared = ImageCache()
/// Private image cache.
private var cache = [String: UIImage]()
// Note, this is `private` to avoid subclassing this; singletons shouldn't be subclassed.
private init() { }
/// Subscript operator to retrieve and update cache
subscript(key: String) -> UIImage? {
get {
return cache[key]
}
set (newValue) {
cache[key] = newValue
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以:
ImageCache.shared["photo1"] = image
let image2 = ImageCache.shared["photo2"])
Run Code Online (Sandbox Code Playgroud)
要么
let cache = ImageCache.shared
cache["photo1"] = image
let image2 = cache["photo2"]
Run Code Online (Sandbox Code Playgroud)
在上面展示了一个简单的单例缓存实现之后,我们应该注意到你可能希望(a)通过使用使其线程安全NSCache
; (b)回应记忆压力.因此,实际的实现类似于Swift 3中的以下内容:
final class ImageCache: NSCache<AnyObject, UIImage> {
static let shared = ImageCache()
/// Observer for `UIApplicationDidReceiveMemoryWarningNotification`.
private var memoryWarningObserver: NSObjectProtocol!
/// Note, this is `private` to avoid subclassing this; singletons shouldn't be subclassed.
///
/// Add observer to purge cache upon memory pressure.
private override init() {
super.init()
memoryWarningObserver = NotificationCenter.default.addObserver(forName: .UIApplicationDidReceiveMemoryWarning, object: nil, queue: nil) { [weak self] notification in
self?.removeAllObjects()
}
}
/// The singleton will never be deallocated, but as a matter of defensive programming (in case this is
/// later refactored to not be a singleton), let's remove the observer if deallocated.
deinit {
NotificationCenter.default.removeObserver(memoryWarningObserver)
}
/// Subscript operation to retrieve and update
subscript(key: String) -> UIImage? {
get {
return object(forKey: key as AnyObject)
}
set (newValue) {
if let object = newValue {
setObject(object, forKey: key as AnyObject)
} else {
removeObject(forKey: key as AnyObject)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
你可以按如下方式使用它:
ImageCache.shared["foo"] = image
Run Code Online (Sandbox Code Playgroud)
和
let image = ImageCache.shared["foo"]
Run Code Online (Sandbox Code Playgroud)
对于Swift 2.3示例,请参阅此答案的上一版本.
归档时间: |
|
查看次数: |
10502 次 |
最近记录: |