Просмотр исходного кода

Merge pull request #17 from onevcat/1.1.2

[WIP] 1.1.2
Wei Wang 10 лет назад
Родитель
Сommit
e73a1ba3b8
4 измененных файлов с 106 добавлено и 25 удалено
  1. 1 1
      Kingfisher-Demo/ViewController.swift
  2. 1 1
      Kingfisher.podspec
  3. 61 3
      Kingfisher/ImageCache.swift
  4. 43 20
      Kingfisher/ImageDownloader.swift

+ 1 - 1
Kingfisher-Demo/ViewController.swift

@@ -57,7 +57,7 @@ extension ViewController: UICollectionViewDataSource {
     
     
     override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
     override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
         let cell = collectionView.dequeueReusableCellWithReuseIdentifier("collectionViewCell", forIndexPath: indexPath) as! CollectionViewCell
         let cell = collectionView.dequeueReusableCellWithReuseIdentifier("collectionViewCell", forIndexPath: indexPath) as! CollectionViewCell
-        cell.cellImageView.kf_setImageWithURL(NSURL(string: "https://raw.githubusercontent.com/onevcat/Kingfisher/master/images/kingfisher-\(indexPath.row + 1).jpg")!, placeholderImage: nil, options: KingfisherOptions.LowPriority, progressBlock: { (receivedSize, totalSize) -> () in
+        cell.cellImageView.kf_setImageWithURL(NSURL(string: "https://raw.githubusercontent.com/onevcat/Kingfisher/master/images/kingfisher-\(indexPath.row + 1).jpg")!, placeholderImage: nil, options: KingfisherOptions.None, progressBlock: { (receivedSize, totalSize) -> () in
             println("\(indexPath.row + 1): \(receivedSize)/\(totalSize)")
             println("\(indexPath.row + 1): \(receivedSize)/\(totalSize)")
         }) { (image, error, imageURL) -> () in
         }) { (image, error, imageURL) -> () in
             println("\(indexPath.row + 1): Finished")
             println("\(indexPath.row + 1): Finished")

+ 1 - 1
Kingfisher.podspec

@@ -1,7 +1,7 @@
 Pod::Spec.new do |s|
 Pod::Spec.new do |s|
 
 
   s.name         = "Kingfisher"
   s.name         = "Kingfisher"
-  s.version      = "1.1.1"
+  s.version      = "1.1.2"
   s.summary      = "A lightweight and pure Swift implemented library for downloading and cacheing image from the web."
   s.summary      = "A lightweight and pure Swift implemented library for downloading and cacheing image from the web."
 
 
   s.description  = <<-DESC
   s.description  = <<-DESC

+ 61 - 3
Kingfisher/ImageCache.swift

@@ -66,7 +66,7 @@ public class ImageCache {
     /// The longest time duration of the cache being stored in disk. Default is 1 week.
     /// The longest time duration of the cache being stored in disk. Default is 1 week.
     public var maxCachePeriodInSecond = defaultMaxCachePeriodInSecond
     public var maxCachePeriodInSecond = defaultMaxCachePeriodInSecond
     
     
-    /// The largest disk size can be taken for the cache. It is the total allocated size of the file in bytes. Default is 0, which means no limit.
+    /// The largest disk size can be taken for the cache. It is the total allocated size of cached files in bytes. Default is 0, which means no limit.
     public var maxDiskCacheSize: UInt = 0
     public var maxDiskCacheSize: UInt = 0
     
     
     private let processQueue = dispatch_queue_create(processQueueName, DISPATCH_QUEUE_CONCURRENT)
     private let processQueue = dispatch_queue_create(processQueueName, DISPATCH_QUEUE_CONCURRENT)
@@ -319,9 +319,9 @@ extension ImageCache {
             self.fileManager.removeItemAtPath(self.diskCachePath, error: nil)
             self.fileManager.removeItemAtPath(self.diskCachePath, error: nil)
             self.fileManager.createDirectoryAtPath(self.diskCachePath, withIntermediateDirectories: true, attributes: nil, error: nil)
             self.fileManager.createDirectoryAtPath(self.diskCachePath, withIntermediateDirectories: true, attributes: nil, error: nil)
             
             
-            if let handler = completionHander {
+            if let completionHander = completionHander {
                 dispatch_async(dispatch_get_main_queue(), { () -> Void in
                 dispatch_async(dispatch_get_main_queue(), { () -> Void in
-                    handler()
+                    completionHander()
                 })
                 })
             }
             }
         })
         })
@@ -423,6 +423,11 @@ extension ImageCache {
 
 
             } else {
             } else {
                 println("Bad disk cache path. \(self.diskCachePath) is not a valid local directory path.")
                 println("Bad disk cache path. \(self.diskCachePath) is not a valid local directory path.")
+                dispatch_async(dispatch_get_main_queue(), { () -> Void in
+                    if let completionHandler = completionHandler {
+                        completionHandler()
+                    }
+                })
             }
             }
         })
         })
     }
     }
@@ -482,6 +487,59 @@ public extension ImageCache {
         
         
         return CacheCheckResult(cached: false, cacheType: nil)
         return CacheCheckResult(cached: false, cacheType: nil)
     }
     }
+    
+    /**
+    Calculate the disk size taken by cache. 
+    It is the total allocated size of the cached files in bytes.
+    
+    :param: completionHandler Called with the calculated size when finishes.
+    */
+    public func calculateDiskCacheSizeWithCompletionHandler(completionHandler: ((size: UInt) -> ())?) {
+        dispatch_async(ioQueue, { () -> Void in
+            if let diskCacheURL = NSURL(fileURLWithPath: self.diskCachePath) {
+                
+                let resourceKeys = [NSURLIsDirectoryKey, NSURLTotalFileAllocatedSizeKey]
+                var diskCacheSize: UInt = 0
+                
+                if let fileEnumerator = self.fileManager.enumeratorAtURL(diskCacheURL,
+                    includingPropertiesForKeys: resourceKeys,
+                    options: NSDirectoryEnumerationOptions.SkipsHiddenFiles,
+                    errorHandler: nil) {
+                        
+                        for fileURL in fileEnumerator.allObjects as! [NSURL] {
+                            
+                            if let resourceValues = fileURL.resourceValuesForKeys(resourceKeys, error: nil) {
+                                // If it is a Directory. Continue to next file URL.
+                                if let isDirectory = resourceValues[NSURLIsDirectoryKey]?.boolValue {
+                                    if isDirectory {
+                                        continue
+                                    }
+                                }
+                                
+                                if let fileSize = resourceValues[NSURLTotalFileAllocatedSizeKey] as? NSNumber {
+                                    diskCacheSize += fileSize.unsignedLongValue
+                                }
+                            }
+                            
+                        }
+                }
+                
+                dispatch_async(dispatch_get_main_queue(), { () -> Void in
+                    if let completionHandler = completionHandler {
+                        completionHandler(size: diskCacheSize)
+                    }
+                })
+                
+            } else {
+                println("Bad disk cache path. \(self.diskCachePath) is not a valid local directory path.")
+                dispatch_async(dispatch_get_main_queue(), { () -> Void in
+                    if let completionHandler = completionHandler {
+                        completionHandler(size: 0)
+                    }
+                })
+            }
+        })
+    }
 }
 }
 
 
 // MARK: - Internal Helper
 // MARK: - Internal Helper

+ 43 - 20
Kingfisher/ImageDownloader.swift

@@ -44,9 +44,16 @@ public class ImageDownloader: NSObject {
     }
     }
     
     
     // MARK: - Public property
     // MARK: - Public property
+    
+    /// This closure will be applied to the image download request before it being sent. You can modify the request for some customizing purpose, like adding auth token to the header or do a url mapping.
+    public var requestModifier: (NSMutableURLRequest -> Void)?
+
     /// The duration before the download is timeout. Default is 15 seconds.
     /// The duration before the download is timeout. Default is 15 seconds.
     public var downloadTimeout: NSTimeInterval = 15.0
     public var downloadTimeout: NSTimeInterval = 15.0
     
     
+    /// A set of trusted hosts when receiving server trust challenges. A challenge with host name contained in this set will be ignored. You can use this set to specify the self-signed site.
+    public var trustedHosts: Set<String>?
+    
     // MARK: - Internal property
     // MARK: - Internal property
     let barrierQueue = dispatch_queue_create(downloaderBarrierName, DISPATCH_QUEUE_CONCURRENT)
     let barrierQueue = dispatch_queue_create(downloaderBarrierName, DISPATCH_QUEUE_CONCURRENT)
     let processQueue = dispatch_queue_create(imageProcessQueueName, DISPATCH_QUEUE_CONCURRENT)
     let processQueue = dispatch_queue_create(imageProcessQueueName, DISPATCH_QUEUE_CONCURRENT)
@@ -108,6 +115,9 @@ public extension ImageDownloader {
             let timeout = self.downloadTimeout == 0.0 ? 15.0 : self.downloadTimeout
             let timeout = self.downloadTimeout == 0.0 ? 15.0 : self.downloadTimeout
             let request = NSMutableURLRequest(URL: URL, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: timeout)
             let request = NSMutableURLRequest(URL: URL, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: timeout)
             request.HTTPShouldUsePipelining = true
             request.HTTPShouldUsePipelining = true
+
+            self.requestModifier?(request)
+            
             let task = session.dataTaskWithRequest(request)
             let task = session.dataTaskWithRequest(request)
             
             
             task.priority = options.lowPriority ? NSURLSessionTaskPriorityLow : NSURLSessionTaskPriorityDefault
             task.priority = options.lowPriority ? NSURLSessionTaskPriorityLow : NSURLSessionTaskPriorityDefault
@@ -183,33 +193,46 @@ extension ImageDownloader: NSURLSessionDataDelegate {
     
     
     public func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
     public func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
         
         
-        let URL = task.originalRequest.URL!
-        
-        if let error = error { // Error happened
-            callbackWithImage(nil, error: error, imageURL: URL)
-        } else { //Download finished without error
-            
-            // We are on main queue when receiving this.
-            dispatch_async(processQueue, { () -> Void in
+        if let URL = task.originalRequest.URL {
+            if let error = error { // Error happened
+                callbackWithImage(nil, error: error, imageURL: URL)
+            } else { //Download finished without error
                 
                 
-                if let fetchLoad = self.fetchLoads[URL] {
-                    if let image = UIImage(data: fetchLoad.responseData) {
-                        if fetchLoad.shouldDecode {
-                            self.callbackWithImage(image.kf_decodedImage(), error: nil, imageURL: URL)
+                // We are on main queue when receiving this.
+                dispatch_async(processQueue, { () -> Void in
+                    
+                    if let fetchLoad = self.fetchLoads[URL] {
+                        if let image = UIImage(data: fetchLoad.responseData) {
+                            if fetchLoad.shouldDecode {
+                                self.callbackWithImage(image.kf_decodedImage(), error: nil, imageURL: URL)
+                            } else {
+                                self.callbackWithImage(image, error: nil, imageURL: URL)
+                            }
+                            
                         } else {
                         } else {
-                            self.callbackWithImage(image, error: nil, imageURL: URL)
+                            self.callbackWithImage(nil, error: NSError(domain: KingfisherErrorDomain, code: KingfisherError.BadData.rawValue, userInfo: nil), imageURL: URL)
                         }
                         }
-
                     } else {
                     } else {
                         self.callbackWithImage(nil, error: NSError(domain: KingfisherErrorDomain, code: KingfisherError.BadData.rawValue, userInfo: nil), imageURL: URL)
                         self.callbackWithImage(nil, error: NSError(domain: KingfisherErrorDomain, code: KingfisherError.BadData.rawValue, userInfo: nil), imageURL: URL)
                     }
                     }
-                } else {
-                    self.callbackWithImage(nil, error: NSError(domain: KingfisherErrorDomain, code: KingfisherError.BadData.rawValue, userInfo: nil), imageURL: URL)
-                }
-                
-                self.cleanForURL(URL)
-            })
+                    
+                    self.cleanForURL(URL)
+                })
+            }
         }
         }
     }
     }
 
 
+    public func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential!) -> Void) {
+
+        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
+            if let trustedHosts = trustedHosts where trustedHosts.contains(challenge.protectionSpace.host) {
+                let credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)
+                completionHandler(.UseCredential, credential)
+                return
+            }
+        }
+        
+        completionHandler(.PerformDefaultHandling, nil)
+    }
+    
 }
 }