diff --git a/.gitignore b/.gitignore
index 7ad8705..ef31253 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,7 @@ DerivedData
*.hmap
*.ipa
*.xcuserstate
+*.DS_Store
# CocoaPods
#
diff --git a/PIImageCache/PIImageCache.xcodeproj/project.pbxproj b/PIImageCache/PIImageCache.xcodeproj/project.pbxproj
index 8fe078e..9ac3d0a 100644
--- a/PIImageCache/PIImageCache.xcodeproj/project.pbxproj
+++ b/PIImageCache/PIImageCache.xcodeproj/project.pbxproj
@@ -173,14 +173,16 @@
8459DB5D1B2910D10046F3FF /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0630;
+ LastUpgradeCheck = 0800;
ORGANIZATIONNAME = pixelink;
TargetAttributes = {
8459DB641B2910D10046F3FF = {
CreatedOnToolsVersion = 6.3.2;
+ LastSwiftMigration = 0800;
};
8459DB791B2910D10046F3FF = {
CreatedOnToolsVersion = 6.3.2;
+ LastSwiftMigration = 0800;
TestTargetID = 8459DB641B2910D10046F3FF;
};
};
@@ -292,14 +294,17 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@@ -336,8 +341,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -356,6 +363,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -366,7 +374,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = PIImageCache/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "jp.pixelink.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 3.0;
};
name = Debug;
};
@@ -376,7 +386,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = PIImageCache/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "jp.pixelink.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 3.0;
};
name = Release;
};
@@ -394,7 +406,9 @@
);
INFOPLIST_FILE = PIImageCacheTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "jp.pixelink.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 3.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PIImageCache.app/PIImageCache";
};
name = Debug;
@@ -409,7 +423,9 @@
);
INFOPLIST_FILE = PIImageCacheTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "jp.pixelink.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 3.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PIImageCache.app/PIImageCache";
};
name = Release;
diff --git a/PIImageCache/PIImageCache/AppDelegate.swift b/PIImageCache/PIImageCache/AppDelegate.swift
index dc1d7dd..9e86ea5 100644
--- a/PIImageCache/PIImageCache/AppDelegate.swift
+++ b/PIImageCache/PIImageCache/AppDelegate.swift
@@ -6,31 +6,31 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
- func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
- func applicationWillResignActive(application: UIApplication) {
+ func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- func applicationDidEnterBackground(application: UIApplication) {
+ func applicationDidEnterBackground(_ application: UIApplication) {
PIImageCache.shared.oldDiskCacheDelete()
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- func applicationWillEnterForeground(application: UIApplication) {
+ func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- func applicationDidBecomeActive(application: UIApplication) {
+ func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- func applicationWillTerminate(application: UIApplication) {
+ func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
diff --git a/PIImageCache/PIImageCache/Info.plist b/PIImageCache/PIImageCache/Info.plist
index 02ef910..6905cc6 100644
--- a/PIImageCache/PIImageCache/Info.plist
+++ b/PIImageCache/PIImageCache/Info.plist
@@ -7,7 +7,7 @@
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
- jp.pixelink.$(PRODUCT_NAME:rfc1034identifier)
+ $(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
diff --git a/PIImageCache/PIImageCache/PIImageCache.swift b/PIImageCache/PIImageCache/PIImageCache.swift
index f1f90df..896ed0c 100644
--- a/PIImageCache/PIImageCache/PIImageCache.swift
+++ b/PIImageCache/PIImageCache/PIImageCache.swift
@@ -3,318 +3,327 @@
import UIKit
-public class PIImageCache {
-
- //initialize
-
- private func myInit() {
- folderCreate()
- prefetchQueueInit()
- }
-
- public init() {
- myInit()
- }
-
- public init(config: Config) {
- dispatch_semaphore_wait(memorySemaphore, DISPATCH_TIME_FOREVER)
- self.config = config
- dispatch_semaphore_signal(memorySemaphore)
- myInit()
- }
-
- public class var shared: PIImageCache {
- struct Static {
- static let instance: PIImageCache = PIImageCache()
+open class PIImageCache {
+
+ //initialize
+
+ fileprivate func myInit() {
+ folderCreate()
+ prefetchQueueInit()
}
- Static.instance.myInit()
- return Static.instance
- }
-
- //public config method
-
- public class Config {
- public var maxMemorySum : Int = 10 // 10 images
- public var limitByteSize : Int = 3 * 1024 * 1024 //3MB
- public var usingDiskCache : Bool = true
- public var diskCacheExpireMinutes : Int = 24 * 60 // 1 day
- public var prefetchOprationCount : Int = 5
- public var cacheRootDirectory : String = NSTemporaryDirectory()
- public var cacheFolderName : String = "PIImageCache"
- }
-
- public func setConfig(config :Config) {
- dispatch_semaphore_wait(memorySemaphore,DISPATCH_TIME_FOREVER)
- self.config = config
- myInit()
- dispatch_semaphore_signal(memorySemaphore)
- }
-
- //public download method
-
- public func get(url: NSURL) -> UIImage? {
- return perform(url).0
- }
-
- public func get(url: NSURL, then: (image:UIImage?) -> Void) {
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
- [weak self] in
- let image = self?.get(url)
- dispatch_async(dispatch_get_main_queue()) {
- then(image: image)
- }
+
+ public init() {
+ myInit()
}
- }
-
- public func getWithId(url: NSURL, id: Int, then: (id: Int, image: UIImage?) -> Void) {
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
- [weak self] in
- let image = self?.get(url)
- dispatch_async(dispatch_get_main_queue()) {
- then(id: id, image: image)
- }
+
+ public init(config: Config) {
+ let _ = memorySemaphore.wait(timeout: DispatchTime.distantFuture)
+ self.config = config
+ memorySemaphore.signal()
+ myInit()
}
- }
-
- public func prefetch(urls: [NSURL]) {
- for url in urls {
- prefetch(url)
+
+ open class var shared: PIImageCache {
+ struct Static {
+ static let instance: PIImageCache = PIImageCache()
+ }
+ Static.instance.myInit()
+ return Static.instance
}
- }
-
- public func prefetch(url: NSURL) {
- var op = NSOperation()
- op.completionBlock = {
- [weak self] in
- self?.downloadToDisk(url)
+
+ //public config method
+
+ open class Config {
+ public init() {}
+ open var maxMemorySum : Int = 10 // 10 images
+ open var limitByteSize : Int = 3 * 1024 * 1024 //3MB
+ open var usingDiskCache : Bool = true
+ open var diskCacheExpireMinutes : Int = 24 * 60 // 1 day
+ open var prefetchOprationCount : Int = 5
+ open var cacheRootDirectory : String = NSTemporaryDirectory()
+ open var cacheFolderName : String = "PIImageCache"
}
- prefetchQueue.addOperation(op)
- }
-
- //public delete method
-
- public func allMemoryCacheDelete() {
- dispatch_semaphore_wait(memorySemaphore, DISPATCH_TIME_FOREVER)
- memoryCache.removeAll(keepCapacity: false)
- dispatch_semaphore_signal(memorySemaphore)
- }
-
- public func allDiskCacheDelete() {
- let path = PIImageCache.folderPath(config)
- dispatch_semaphore_wait(diskSemaphore, DISPATCH_TIME_FOREVER)
- let allFileName: [String]? = fileManager.contentsOfDirectoryAtPath(path, error: nil) as? [String]
- if let all = allFileName {
- for fileName in all {
- fileManager.removeItemAtPath(path + fileName, error: nil)
- }
+
+ open func setConfig(_ config :Config) {
+ let _ = memorySemaphore.wait(timeout: DispatchTime.distantFuture)
+ self.config = config
+ myInit()
+ memorySemaphore.signal()
}
- folderCreate()
- dispatch_semaphore_signal(diskSemaphore)
- }
-
- public func oldDiskCacheDelete() {
- let path = PIImageCache.folderPath(config)
- dispatch_semaphore_wait(diskSemaphore, DISPATCH_TIME_FOREVER)
- let allFileName: [String]? = fileManager.contentsOfDirectoryAtPath(path, error: nil) as? [String]
- if let all = allFileName {
- for fileName in all {
- if let attr = fileManager.attributesOfItemAtPath(path + fileName, error: nil) {
- let diff = NSDate().timeIntervalSinceDate( (attr[NSFileModificationDate] as? NSDate) ?? NSDate() )
- if Double(diff) > Double(config.diskCacheExpireMinutes * 60) {
- fileManager.removeItemAtPath(path + fileName, error: nil)
- }
+
+ //public download method
+
+ open func get(_ url: URL) -> UIImage? {
+ return perform(url).0
+ }
+
+ open func get(_ url: URL, then: @escaping (_ image:UIImage?) -> Void) {
+ DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {
+ [weak self] in
+ let image = self?.get(url)
+ DispatchQueue.main.async {
+ then(image)
+ }
+ }
+ }
+
+ open func getWithId(_ url: URL, id: Int, then: @escaping (_ id: Int, _ image: UIImage?) -> Void) {
+ DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {
+ [weak self] in
+ let image = self?.get(url)
+ DispatchQueue.main.async {
+ then(id, image)
+ }
}
- }
}
- folderCreate()
- dispatch_semaphore_signal(diskSemaphore)
- }
-
- //member
-
- private var config: Config = Config()
- private var memoryCache : [memoryCacheImage] = []
- private var memorySemaphore = dispatch_semaphore_create(1)
- private var diskSemaphore = dispatch_semaphore_create(1)
- private let fileManager = NSFileManager.defaultManager()
- private let prefetchQueue = NSOperationQueue()
-
- private struct memoryCacheImage {
- let image :UIImage
- var timeStamp :Double
- let url :NSURL
- }
-
- // memory cache
-
- private func memoryCacheRead(url: NSURL) -> UIImage? {
- for var i=0; i Double(config.diskCacheExpireMinutes * 60) {
+ try fileManager.removeItem(atPath: path + fileName)
+ }
+
+ }
+ }
+ folderCreate()
+ diskSemaphore.signal()
+ } catch {}
+ }
+
+ //member
+
+ fileprivate var config: Config = Config()
+ fileprivate var memoryCache : [memoryCacheImage] = []
+ fileprivate var memorySemaphore = DispatchSemaphore(value: 1)
+ fileprivate var diskSemaphore = DispatchSemaphore(value: 1)
+ fileprivate let fileManager = FileManager.default
+ fileprivate let prefetchQueue = OperationQueue()
+
+ fileprivate struct memoryCacheImage {
+ let image :UIImage
+ var timeStamp :Double
+ let url :URL
+ }
+
+ // memory cache
+
+ fileprivate func memoryCacheRead(_ url: URL) -> UIImage? {
for i in 0 ..< memoryCache.count {
- if old.1 < memoryCache[i].timeStamp {
- old = (i,memoryCache[i].timeStamp)
- }
+ if url == memoryCache[i].url {
+ memoryCache[i].timeStamp = now
+ return memoryCache[i].image
+ }
}
- memoryCache.removeAtIndex(old.0)
- }
- memoryCache.append(memoryCacheImage(image: image, timeStamp:now, url: url))
+ return nil
}
- }
-
- //disk cache
-
-
- private func diskCacheRead(url: NSURL) -> UIImage? {
- if let path = PIImageCache.filePath(url, config: config) {
- return UIImage(contentsOfFile: path)
+
+ fileprivate func memoryCacheWrite(_ url:URL,image:UIImage) {
+ switch memoryCache.count {
+ case 0 ... config.maxMemorySum:
+ memoryCache.append(memoryCacheImage(image: image, timeStamp: now, url: url))
+ case config.maxMemorySum + 1://+1 because 0 origin
+ var old = (0,now)
+ for i in 0 ..< memoryCache.count {
+ if old.1 < memoryCache[i].timeStamp {
+ old = (i,memoryCache[i].timeStamp)
+ }
+ }
+ memoryCache.remove(at: old.0)
+ memoryCache.append(memoryCacheImage(image: image, timeStamp:now, url: url))
+ default:
+ for _ in 0 ... 1 {
+ var old = (0,now)
+ for i in 0 ..< memoryCache.count {
+ if old.1 < memoryCache[i].timeStamp {
+ old = (i,memoryCache[i].timeStamp)
+ }
+ }
+ memoryCache.remove(at: old.0)
+ }
+ memoryCache.append(memoryCacheImage(image: image, timeStamp:now, url: url))
+ }
}
- return nil
- }
-
- private func diskCacheWrite(url:NSURL,image:UIImage) {
- if let path = PIImageCache.filePath(url, config: config) {
- NSData(data: UIImagePNGRepresentation(image)).writeToFile(path, atomically: true)
+
+ //disk cache
+
+
+ fileprivate func diskCacheRead(_ url: URL) -> UIImage? {
+ if let path = PIImageCache.filePath(url, config: config) {
+ return UIImage(contentsOfFile: path)
+ }
+ return nil
}
- }
-
- //private download
-
- internal enum Result {
- case Mishit, MemoryHit, DiskHit
- }
-
- internal func download(url: NSURL) -> (UIImage, byteSize: Int)? {
- var err: NSError?
- var maybeImageData = NSData(contentsOfURL: url, options:.UncachedRead, error: &err)
- if let e = err { println(e) }
- if let imageData = maybeImageData {
- if let image = UIImage(data: imageData) {
- let bytes = imageData.length
- return (image, bytes)
- }
+
+ fileprivate func diskCacheWrite(_ url:URL,image:UIImage) {
+ if let path = PIImageCache.filePath(url, config: config) {
+ _ = NSData(data: UIImagePNGRepresentation(image)!).write(toFile: path, atomically: true)
+ }
}
- return nil
- }
-
- internal func perform(url: NSURL) -> (UIImage?, Result) {
-
- //memory read
- dispatch_semaphore_wait(memorySemaphore, DISPATCH_TIME_FOREVER)
- let maybeMemoryCache = memoryCacheRead(url)
- dispatch_semaphore_signal(memorySemaphore)
- if let cache = maybeMemoryCache {
- return (cache, .MemoryHit)
+
+ //private download
+
+ internal enum Result {
+ case mishit, memoryHit, diskHit
}
- //disk read
- if config.usingDiskCache {
- dispatch_semaphore_wait(diskSemaphore, DISPATCH_TIME_FOREVER)
- let maybeDiskCache = diskCacheRead(url)
- dispatch_semaphore_signal(diskSemaphore)
- if let cache = maybeDiskCache {
- dispatch_semaphore_wait(memorySemaphore, DISPATCH_TIME_FOREVER)
- memoryCacheWrite(url, image: cache)
- dispatch_semaphore_signal(memorySemaphore)
- return (cache, .DiskHit)
- }
+ internal func download(_ url: URL) -> (UIImage, byteSize: Int)? {
+ do {
+ let maybeImageData = try NSData(contentsOf: url, options: .uncachedRead)
+ let imageData = maybeImageData
+ if let image = UIImage(data: imageData as Data) {
+ let bytes = imageData.length
+ return (image, bytes)
+ }
+
+ } catch {}
+ return nil
+
}
- //download
- let maybeImage = download(url)
- if let (image, byteSize) = maybeImage {
- if byteSize < config.limitByteSize {
- //write memory
- dispatch_semaphore_wait(memorySemaphore, DISPATCH_TIME_FOREVER)
- memoryCacheWrite(url, image: image)
- dispatch_semaphore_signal(memorySemaphore)
- //write disk
+ internal func perform(_ url: URL) -> (UIImage?, Result) {
+
+ //memory read
+ let _ = memorySemaphore.wait(timeout: DispatchTime.distantFuture)
+ let maybeMemoryCache = memoryCacheRead(url)
+ memorySemaphore.signal()
+ if let cache = maybeMemoryCache {
+ return (cache, .memoryHit)
+ }
+
+ //disk read
if config.usingDiskCache {
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
- [weak self] in
- if let scope = self {
- dispatch_semaphore_wait(scope.diskSemaphore, DISPATCH_TIME_FOREVER)
- scope.diskCacheWrite(url, image: image)
- dispatch_semaphore_signal(scope.diskSemaphore)
+ let _ = diskSemaphore.wait(timeout: DispatchTime.distantFuture)
+ let maybeDiskCache = diskCacheRead(url)
+ diskSemaphore.signal()
+ if let cache = maybeDiskCache {
+ let _ = memorySemaphore.wait(timeout: DispatchTime.distantFuture)
+ memoryCacheWrite(url, image: cache)
+ memorySemaphore.signal()
+ return (cache, .diskHit)
}
- }
}
- }
+
+ //download
+ let maybeImage = download(url)
+ if let (image, byteSize) = maybeImage {
+ if byteSize < config.limitByteSize {
+ //write memory
+ let _ = memorySemaphore.wait(timeout: DispatchTime.distantFuture)
+ memoryCacheWrite(url, image: image)
+ memorySemaphore.signal()
+ //write disk
+ if config.usingDiskCache {
+ DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {
+ [weak self] in
+ if let scope = self {
+ let _ = scope.diskSemaphore.wait(timeout: DispatchTime.distantFuture)
+ scope.diskCacheWrite(url, image: image)
+ scope.diskSemaphore.signal()
+ }
+ }
+ }
+ }
+ }
+ return (maybeImage?.0, .mishit)
+ }
+
+ fileprivate func downloadToDisk(_ url: URL) {
+ let path = PIImageCache.filePath(url, config: config)
+ if path == nil { return }
+ if fileManager.fileExists(atPath: path!) { return }
+ let maybeImage = download(url)
+ if let (image, byteSize) = maybeImage {
+ if byteSize < config.limitByteSize {
+ let _ = diskSemaphore.wait(timeout: DispatchTime.distantFuture)
+ diskCacheWrite(url, image: image)
+ diskSemaphore.signal()
+ }
+ }
+ }
+
+ //util
+
+ fileprivate var now: Double {
+ get {
+ return Date().timeIntervalSince1970
+ }
}
- return (maybeImage?.0, .Mishit)
- }
-
- private func downloadToDisk(url: NSURL) {
- let path = PIImageCache.filePath(url, config: config)
- if path == nil { return }
- if fileManager.fileExistsAtPath(path!) { return }
- let maybeImage = download(url)
- if let (image, byteSize) = maybeImage {
- if byteSize < config.limitByteSize {
- dispatch_semaphore_wait(diskSemaphore, DISPATCH_TIME_FOREVER)
- diskCacheWrite(url, image: image)
- dispatch_semaphore_signal(diskSemaphore)
- }
+
+ fileprivate func folderCreate() {
+ do {
+ let path = "\(config.cacheRootDirectory)\(config.cacheFolderName)/"
+ try fileManager.createDirectory(atPath: path, withIntermediateDirectories: false, attributes: nil)
+ } catch {}
}
- }
-
- //util
-
- private var now: Double {
- get {
- return NSDate().timeIntervalSince1970
+
+ fileprivate class func filePath(_ url: URL, config:Config) -> String? {
+ let urlstr = String(url.absoluteString.characters.reversed())
+ var code = ""
+ var maxLength: Int = 40
+ for char in urlstr.utf8 {
+ code = code + "u\(char)"
+ maxLength -= 1
+ if maxLength == 0 {
+ break
+ }
+ }
+ return "\(config.cacheRootDirectory)\(config.cacheFolderName)/\(code)"
+
+ //return nil
}
- }
-
- private func folderCreate() {
- let path = "\(config.cacheRootDirectory)\(config.cacheFolderName)/"
- if fileManager.createDirectoryAtPath(
- path,
- withIntermediateDirectories: false,
- attributes: nil,
- error: nil){}
- }
-
- private class func filePath(url: NSURL, config:Config) -> String? {
- if let urlstr = url.absoluteString {
- var code = ""
- for char in urlstr.utf8 {
- code = code + "u\(char)"
- }
- return "\(config.cacheRootDirectory)\(config.cacheFolderName)/\(code)"
+
+ fileprivate class func folderPath(_ config: Config) -> String {
+ return "\(config.cacheRootDirectory)\(config.cacheFolderName)/"
+ }
+
+ fileprivate func prefetchQueueInit(){
+ prefetchQueue.maxConcurrentOperationCount = config.prefetchOprationCount
+ prefetchQueue.qualityOfService = QualityOfService.background
}
- return nil
- }
-
- private class func folderPath(config: Config) -> String {
- return "\(config.cacheRootDirectory)\(config.cacheFolderName)/"
- }
-
- private func prefetchQueueInit(){
- prefetchQueue.maxConcurrentOperationCount = config.prefetchOprationCount
- prefetchQueue.qualityOfService = NSQualityOfService.Background
- }
-
-}
\ No newline at end of file
+
+}
diff --git a/PIImageCache/PIImageCache/PIImageCacheExtensions.swift b/PIImageCache/PIImageCache/PIImageCacheExtensions.swift
index f2ee51d..3cac634 100644
--- a/PIImageCache/PIImageCache/PIImageCacheExtensions.swift
+++ b/PIImageCache/PIImageCache/PIImageCacheExtensions.swift
@@ -3,46 +3,46 @@
import UIKit
-public extension NSURL {
- public func getImageWithCache() -> UIImage? {
- return PIImageCache.shared.get(self)
- }
-
- public func getImageWithCache(cache: PIImageCache) -> UIImage? {
- return cache.get(self)
- }
+public extension URL {
+ public func getImageWithCache() -> UIImage? {
+ return PIImageCache.shared.get(self)
+ }
+
+ public func getImageWithCache(_ cache: PIImageCache) -> UIImage? {
+ return cache.get(self)
+ }
}
public extension UIImageView {
- public func imageOfURL(url: NSURL) {
- PIImageCache.shared.get(url) {
- [weak self] img in
- self?.image = img
+ public func imageOfURL(_ url: URL) {
+ PIImageCache.shared.get(url) {
+ [weak self] img in
+ self?.image = img
+ }
}
- }
-
- public func imageOfURL(url: NSURL, cache: PIImageCache) {
- cache.get(url) {
- [weak self] img in
- self?.image = img
+
+ public func imageOfURL(_ url: URL, cache: PIImageCache) {
+ cache.get(url) {
+ [weak self] img in
+ self?.image = img
+ }
}
- }
-
- public func imageOfURL(url: NSURL, then:(Bool)->Void) {
- PIImageCache.shared.get(url) {
- [weak self] img in
- let isOK = img != nil
- self?.image = img
- then(isOK)
+
+ public func imageOfURL(_ url: URL, then:@escaping (Bool)->Void) {
+ PIImageCache.shared.get(url) {
+ [weak self] img in
+ let isOK = img != nil
+ self?.image = img
+ then(isOK)
+ }
}
- }
-
- public func imageOfURL(url: NSURL, cache: PIImageCache, then:(Bool)->Void) {
- cache.get(url) {
- [weak self] img in
- let isOK = img != nil
- self?.image = img
- then(isOK)
+
+ public func imageOfURL(_ url: URL, cache: PIImageCache, then:@escaping (Bool)->Void) {
+ cache.get(url) {
+ [weak self] img in
+ let isOK = img != nil
+ self?.image = img
+ then(isOK)
+ }
}
- }
-}
\ No newline at end of file
+}
diff --git a/PIImageCache/PIImageCache/TableViewController.swift b/PIImageCache/PIImageCache/TableViewController.swift
index 0b7146e..72bb2e7 100644
--- a/PIImageCache/PIImageCache/TableViewController.swift
+++ b/PIImageCache/PIImageCache/TableViewController.swift
@@ -11,9 +11,9 @@ class TableViewController : UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
- var urls: [NSURL] = []
+ var urls: [URL] = []
for category in lormpixelCategory {
- urls.append( NSURL(string: "http://lorempixel.com/200/200/" + category)! )
+ urls.append( URL(string: "http://lorempixel.com/200/200/" + category)! )
}
PIImageCache.shared.prefetch(urls)
}
@@ -21,18 +21,17 @@ class TableViewController : UITableViewController {
let lormpixelCategory =
[ "abstract", "animals", "business", "cats", "city", "food", "nightlife", "fashion", "people", "nature", "sports", "technics", "transport", "abstract", "animals", "business", "cats", "city", "food", "nightlife", "fashion", "people", "nature", "sports", "technics", "transport" ]
- override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+ override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return lormpixelCategory.count
}
- override func tableView(tableView: UITableView,
- cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
- let cell: TableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! TableViewCell
- let i = indexPath.row
+ override func tableView(_ tableView: UITableView,
+ cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ let cell: TableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
+ let i = (indexPath as NSIndexPath).row
cell.id = i
- let url = NSURL(string: "http://lorempixel.com/200/200/" + lormpixelCategory[i] )!
- PIImageCache.shared.getWithId(url, id: i) {
- [weak self] id, image in
+ let url = URL(string: "http://lorempixel.com/200/200/" + lormpixelCategory[i] )!
+ PIImageCache.shared.getWithId(url, id: i) { (id, image) in
if id == cell.id {
cell.icon.image = image
}
diff --git a/PIImageCache/PIImageCache/ViewController.swift b/PIImageCache/PIImageCache/ViewController.swift
index 2cb5508..dd4ca67 100644
--- a/PIImageCache/PIImageCache/ViewController.swift
+++ b/PIImageCache/PIImageCache/ViewController.swift
@@ -14,12 +14,12 @@ class ViewController: UIViewController {
var count = 0
@IBOutlet var imgView: UIImageView!
- @IBAction func btnPushed(sender: AnyObject) {
- count++
+ @IBAction func btnPushed(_ sender: AnyObject) {
+ count += 1
if count >= lormpixelCategory.count {
count = 0
}
- let url = NSURL(string: "http://lorempixel.com/200/200/" + lormpixelCategory[count] )!
+ let url = URL(string: "http://lorempixel.com/200/200/" + lormpixelCategory[count] )!
imgView.imageOfURL(url)
}
@@ -27,4 +27,4 @@ class ViewController: UIViewController {
cache.allMemoryCacheDelete()
}
-}
\ No newline at end of file
+}
diff --git a/PIImageCache/PIImageCacheTests/Info.plist b/PIImageCache/PIImageCacheTests/Info.plist
index 2fa0136..ba72822 100644
--- a/PIImageCache/PIImageCacheTests/Info.plist
+++ b/PIImageCache/PIImageCacheTests/Info.plist
@@ -7,7 +7,7 @@
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
- jp.pixelink.$(PRODUCT_NAME:rfc1034identifier)
+ $(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
diff --git a/PIImageCache/PIImageCacheTests/PIImageCacheBasicTests.swift b/PIImageCache/PIImageCacheTests/PIImageCacheBasicTests.swift
index 5e940f9..6f7611c 100644
--- a/PIImageCache/PIImageCacheTests/PIImageCacheBasicTests.swift
+++ b/PIImageCache/PIImageCacheTests/PIImageCacheBasicTests.swift
@@ -9,7 +9,7 @@ class PIImageBasicCacheTests: XCTestCase {
func testREADME() {
//NSURL extension
- let url = NSURL(string: "http://place-hold.it/200x200")!
+ let url = URL(string: "http://place-hold.it/200x200")!
var image = url.getImageWithCache()
XCTAssert(image!.size.width == 200 && image!.size.height == 200 , "Pass")
@@ -21,10 +21,10 @@ class PIImageBasicCacheTests: XCTestCase {
}
//for Background
- var cache = PIImageCache() // or PIImageCache.sherd
+ let cache = PIImageCache() // or PIImageCache.sherd
image = cache.get(url)!
XCTAssert(image!.size.width == 200 && image!.size.height == 200 , "Pass")
- var config = PIImageCache.Config()
+ let config = PIImageCache.Config()
config.maxMemorySum = 5
config.limitByteSize = 100 * 1024 // 100kB
cache.setConfig(config)
diff --git a/PIImageCache/PIImageCacheTests/PIImageCacheDiskCacheTests.swift b/PIImageCache/PIImageCacheTests/PIImageCacheDiskCacheTests.swift
index 13f9fe0..6e478dc 100644
--- a/PIImageCache/PIImageCacheTests/PIImageCacheDiskCacheTests.swift
+++ b/PIImageCache/PIImageCacheTests/PIImageCacheDiskCacheTests.swift
@@ -11,43 +11,45 @@ class PIImageDiskCacheTests: XCTestCase {
func testDiskCache() {
let cache = PIImageCache()
var image: UIImage?, result: PIImageCache.Result
- var urls :[NSURL] = []
+ var urls :[URL] = []
for i in 0 ..< max * 2 {
- urls.append(NSURL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
+ urls.append(URL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
}
for i in 0 ..< max * 2 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
XCTAssert(image!.size.width == 200 && image!.size.height == 200 , "Pass")
}
for i in 0 ..< max * 2 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result == .DiskHit, "Pass")
+ XCTAssert(result == .diskHit, "Pass")
XCTAssert(image!.size.width == 200 && image!.size.height == 200 , "Pass")
}
}
func testFileTimeStamp() {
+ do {
PIImageCache.shared.oldDiskCacheDelete()
let config = PIImageCache.Config()
let path = "\(config.cacheRootDirectory)\(config.cacheFolderName)/"
- let allFileName: [String]? = NSFileManager.defaultManager().contentsOfDirectoryAtPath(path, error: nil) as? [String]
+ let allFileName: [String]? = try FileManager.default.contentsOfDirectory(atPath: path)
if let all = allFileName {
for fileName in all {
- if let attr = NSFileManager.defaultManager().attributesOfItemAtPath(path + fileName, error: nil) {
- let diff = NSDate().timeIntervalSinceDate( (attr[NSFileModificationDate] as? NSDate) ?? NSDate(timeIntervalSince1970: 0) )
+ let attr = try FileManager.default.attributesOfItem(atPath: path + fileName)
+ let diff = Date().timeIntervalSince( (attr[FileAttributeKey.modificationDate] as? Date) ?? Date(timeIntervalSince1970: 0) )
XCTAssert( Double(diff) <= Double(config.diskCacheExpireMinutes * 60) , "Pass")
- }
+
}
}
+ } catch {}
}
func testPrefetch() {
let cache = PIImageCache()
var image: UIImage?, result: PIImageCache.Result
- var urls :[NSURL] = []
+ var urls :[URL] = []
for i in 0 ..< max * 2 {
- urls.append(NSURL(string: "http://place-hold.it/200x200/2ff&text=BackgroundNo.\(i)")!)
+ urls.append(URL(string: "http://place-hold.it/200x200/2ff&text=BackgroundNo.\(i)")!)
}
cache.prefetch(urls)
for i in 0 ..< max * 2 {
@@ -56,7 +58,7 @@ class PIImageDiskCacheTests: XCTestCase {
}
for i in 0 ..< max * 2 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result != .Mishit, "Pass")
+ XCTAssert(result != .mishit, "Pass")
XCTAssert(image!.size.width == 200 && image!.size.height == 200 , "Pass")
}
}
diff --git a/PIImageCache/PIImageCacheTests/PIImageMemoryCacheTests.swift b/PIImageCache/PIImageCacheTests/PIImageMemoryCacheTests.swift
index dd51ec2..1ff9e98 100644
--- a/PIImageCache/PIImageCacheTests/PIImageMemoryCacheTests.swift
+++ b/PIImageCache/PIImageCacheTests/PIImageMemoryCacheTests.swift
@@ -7,13 +7,13 @@ import XCTest
class PIImageMemoryCacheTests: XCTestCase {
let max = PIImageCache.Config().maxMemorySum
- let url = NSURL(string: "http://place-hold.it/200x200")!
+ let url = URL(string: "http://place-hold.it/200x200")!
- func check(image: UIImage?) {
+ func check(_ image: UIImage?) {
XCTAssert(image!.size.width == 200 && image!.size.height == 200 , "Pass")
}
- func checkSize(dataSize: Int) {
+ func checkSize(_ dataSize: Int) {
XCTAssert(dataSize == 926 , "Pass")
}
@@ -29,48 +29,48 @@ class PIImageMemoryCacheTests: XCTestCase {
var image: UIImage?, result: PIImageCache.Result
(image, result) = cache.perform(url)
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
(image, result) = cache.perform(url)
- XCTAssert(result == .MemoryHit, "Pass")
+ XCTAssert(result == .memoryHit, "Pass")
check(image)
}
func testCacheLimit() {
let cache = PIImageCache()
var image: UIImage?, result: PIImageCache.Result
- var urls :[NSURL] = []
+ var urls :[URL] = []
for i in 0 ..< max + 5 {
- urls.append(NSURL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
+ urls.append(URL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
}
for i in 0 ..< max {
(image, result) = cache.perform(urls[i])
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}
for i in 0 ..< max {
(image, result) = cache.perform(urls[i])
- XCTAssert(result == .MemoryHit, "Pass")
+ XCTAssert(result == .memoryHit, "Pass")
check(image)
}
for i in max ..< max + 5 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}
for i in 0 ..< max {
(image, result) = cache.perform(urls[i])
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}
for i in 0 ..< max {
(image, result) = cache.perform(urls[i])
- XCTAssert(result == .MemoryHit, "Pass")
+ XCTAssert(result == .memoryHit, "Pass")
check(image)
}
for i in max ..< max + 5 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}
}
@@ -79,18 +79,18 @@ class PIImageMemoryCacheTests: XCTestCase {
let cache1 = PIImageCache.shared
let cache2 = PIImageCache.shared
var image: UIImage?, result: PIImageCache.Result
- var urls :[NSURL] = []
+ var urls :[URL] = []
for i in 0 ..< max {
- urls.append(NSURL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
+ urls.append(URL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
}
for i in 0 ..< max {
(image, result) = cache1.perform(urls[i])
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}
for i in 0 ..< max {
(image, result) = cache2.perform(urls[i])
- XCTAssert(result == .MemoryHit, "Pass")
+ XCTAssert(result == .memoryHit, "Pass")
check(image)
}
}
@@ -101,23 +101,23 @@ class PIImageMemoryCacheTests: XCTestCase {
config.limitByteSize = 3 * 1024 * 1024
let cache = PIImageCache(config: config)
var image: UIImage?, result: PIImageCache.Result
- var urls :[NSURL] = []
+ var urls :[URL] = []
for i in 0 ..< max {
- urls.append(NSURL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
+ urls.append(URL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
}
for i in 0 ..< max / 2 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}
for i in 0 ..< max / 2 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result == .MemoryHit, "Pass")
+ XCTAssert(result == .memoryHit, "Pass")
check(image)
}
for i in max / 2 ..< max {
(image, result) = cache.perform(urls[i])
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}
}
@@ -130,10 +130,10 @@ class PIImageMemoryCacheTests: XCTestCase {
var image: UIImage?, result: PIImageCache.Result
(image, result) = cache.perform(url)
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
(image, result) = cache.perform(url)
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}
@@ -174,13 +174,13 @@ class PIImageMemoryCacheTests: XCTestCase {
}
func testThreadSafetySyncGet() {
- var urls :[NSURL] = []
+ var urls :[URL] = []
for i in 0 ..< 50 {
- urls.append(NSURL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
+ urls.append(URL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
}
let cache = PIImageCache()
for i in 0 ..< 10000 {
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
+ DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.default).async {
let image = cache.get(urls[i % 50])!
XCTAssert(image.size.width == 200 && image.size.height == 200 , "Pass")
}
@@ -188,13 +188,13 @@ class PIImageMemoryCacheTests: XCTestCase {
}
func testThreadSafetyAsyncGet() {
- var urls :[NSURL] = []
+ var urls :[URL] = []
for i in 0 ..< 50 {
- urls.append(NSURL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
+ urls.append(URL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
}
let cache = PIImageCache()
for i in 0 ..< 10000 {
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
+ DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.default).async {
cache.get(urls[i % 50]) {
[weak self] image in
self?.check(image)
@@ -204,9 +204,9 @@ class PIImageMemoryCacheTests: XCTestCase {
}
func testChangeConfigInRunTime() {
- var urls :[NSURL] = []
+ var urls :[URL] = []
for i in 0 ..< 5 {
- urls.append(NSURL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
+ urls.append(URL(string: "http://place-hold.it/200x200/2ff&text=No.\(i)")!)
}
var image: UIImage?, result: PIImageCache.Result
@@ -217,13 +217,13 @@ class PIImageMemoryCacheTests: XCTestCase {
for i in 0 ..< 5 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}
for i in 0 ..< 5 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result == .MemoryHit, "Pass")
+ XCTAssert(result == .memoryHit, "Pass")
check(image)
}
@@ -232,13 +232,13 @@ class PIImageMemoryCacheTests: XCTestCase {
for i in 0 ..< 2 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}
for i in 0 ..< 2 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result == .MemoryHit, "Pass")
+ XCTAssert(result == .memoryHit, "Pass")
check(image)
}
@@ -247,13 +247,13 @@ class PIImageMemoryCacheTests: XCTestCase {
for i in 3 ..< 5 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}
for i in 3 ..< 5 {
(image, result) = cache.perform(urls[i])
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}
}
@@ -263,11 +263,11 @@ class PIImageMemoryCacheTests: XCTestCase {
var image: UIImage?, result: PIImageCache.Result
(image, result) = cache.perform(url)
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
cache.allMemoryCacheDelete()
(image, result) = cache.perform(url)
- XCTAssert(result != .MemoryHit, "Pass")
+ XCTAssert(result != .memoryHit, "Pass")
check(image)
}