import Foundation /*private final class ImageCacheData { let size: CGSize let bytesPerRow: Int var data: NSPurgeableData var isDiscarded: Bool { return self.data.isContentDiscarded() } var image: UIImage? { if self.data.beginContentAccess() { return self.createImage() } return nil } init(size: CGSize, generator: (CGContext) -> Void, takenImage: @noescape(UIImage) -> Void) { self.size = size self.bytesPerRow = (4 * Int(size.width) + 15) & (~15) self.data = NSPurgeableData(length: self.bytesPerRow * Int(size.height))! let colorSpace = CGColorSpaceCreateDeviceRGB() let bitmapInfo = CGImageAlphaInfo.PremultipliedFirst.rawValue | CGBitmapInfo.ByteOrder32Little.rawValue if let context = CGBitmapContextCreate(self.data.mutableBytes, Int(size.width), Int(size.height), 8, bytesPerRow, colorSpace, bitmapInfo) { CGContextTranslateCTM(context, size.width / 2.0, size.height / 2.0) CGContextScaleCTM(context, 1.0, -1.0) CGContextTranslateCTM(context, -size.width / 2.0, -size.height / 2.0) UIGraphicsPushContext(context) generator(context) UIGraphicsPopContext() } takenImage(self.createImage()) } private func createImage() -> UIImage { let colorSpace = CGColorSpaceCreateDeviceRGB() let bitmapInfo = CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue let unmanagedData = withUnsafePointer(&self.data, { pointer in return Unmanaged.fromOpaque(COpaquePointer(pointer)) }) unmanagedData.retain() let dataProvider = CGDataProviderCreateWithData(UnsafeMutablePointer(unmanagedData.toOpaque()), self.data.bytes, self.bytesPerRow, { info, _, _ in let unmanagedData = Unmanaged.fromOpaque(COpaquePointer(info)) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), { unmanagedData.takeUnretainedValue().endContentAccess() unmanagedData.release() }) }) let image = CGImageCreate(Int(self.size.width), Int(self.size.height), 8, 32, self.bytesPerRow, colorSpace, CGBitmapInfo(rawValue: bitmapInfo), dataProvider, nil, false, CGColorRenderingIntent(rawValue: 0)!) let result = UIImage(CGImage: image!) return result } } private final class ImageCacheResidentImage { let key: String let image: UIImage var accessIndex: Int init(key: String, image: UIImage, accessIndex: Int) { self.key = key self.image = image self.accessIndex = accessIndex } } public final class ImageCache { let maxResidentSize: Int var mutex = pthread_mutex_t() private var imageDatas: [String : ImageCacheData] = [:] private var residentImages: [String : ImageCacheResidentImage] = [:] var nextAccessIndex = 1 var residentImagesSize = 0 public init(maxResidentSize: Int) { self.maxResidentSize = maxResidentSize pthread_mutex_init(&self.mutex, nil) } deinit { pthread_mutex_destroy(&self.mutex) } public func addImageForKey(key: String, size: CGSize, generator: CGContextRef -> Void) { var image: UIImage? let imageData = ImageCacheData(size: size, generator: generator, takenImage: { image = $0 }) pthread_mutex_lock(&self.mutex) self.imageDatas[key] = imageData self.addResidentImage(image!, forKey: key) pthread_mutex_unlock(&self.mutex) } public func imageForKey(key: String) -> UIImage? { var image: UIImage? pthread_mutex_lock(&self.mutex); if let residentImage = self.residentImages[key] { image = residentImage.image self.nextAccessIndex += 1 residentImage.accessIndex = self.nextAccessIndex } else { if let imageData = self.imageDatas[key] { if let takenImage = imageData.image { image = takenImage self.addResidentImage(takenImage, forKey: key) } else { self.imageDatas.removeValueForKey(key) } } } pthread_mutex_unlock(&self.mutex) return image } private func addResidentImage(image: UIImage, forKey key: String) { let imageSize = Int(image.size.width * image.size.height * image.scale) * 4 if self.residentImagesSize + imageSize > self.maxResidentSize { let sizeToRemove = self.residentImagesSize - (self.maxResidentSize - imageSize) let sortedImages = self.residentImages.values.sort({ $0.accessIndex < $1.accessIndex }) var removedSize = 0 var i = sortedImages.count - 1 while i >= 0 && removedSize < sizeToRemove { let currentImage = sortedImages[i] let currentImageSize = Int(currentImage.image.size.width * currentImage.image.size.height * currentImage.image.scale) * 4 removedSize += currentImageSize self.residentImages.removeValueForKey(currentImage.key) i -= 1 } self.residentImagesSize = max(0, self.residentImagesSize - removedSize) } self.residentImagesSize += imageSize self.nextAccessIndex += 1 self.residentImages[key] = ImageCacheResidentImage(key: key, image: image, accessIndex: self.nextAccessIndex) } }*/