Procházet zdrojové kódy

Merge pull request #116 from onevcat/fix/reload-flicking

Prevent dispatch if already on main thread
Wei Wang před 10 roky
rodič
revize
776e2819d6

+ 4 - 0
Kingfisher.xcodeproj/project.pbxproj

@@ -21,6 +21,7 @@
 		D11250C11BAC4B6300B986EF /* ImageTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = D11250C01BAC4B6300B986EF /* ImageTransition.swift */; settings = {ASSET_TAGS = (); }; };
 		D151E72B1AD3C48D004FD4AE /* UIImage+Decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D151E72A1AD3C48D004FD4AE /* UIImage+Decode.swift */; };
 		D166E4CD1B73820700B129E3 /* UIImage+Normalize.swift in Sources */ = {isa = PBXBuildFile; fileRef = D166E4CC1B73820700B129E3 /* UIImage+Normalize.swift */; };
+		D1B1B9901BC7EB7100DE20D8 /* ThreadHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1B1B98F1BC7EB7100DE20D8 /* ThreadHelper.swift */; settings = {ASSET_TAGS = (); }; };
 		D1ED2D111AD2CFA600CFC3EB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1ED2D101AD2CFA600CFC3EB /* AppDelegate.swift */; };
 		D1ED2D131AD2CFA600CFC3EB /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1ED2D121AD2CFA600CFC3EB /* ViewController.swift */; };
 		D1ED2D161AD2CFA600CFC3EB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D1ED2D141AD2CFA600CFC3EB /* Main.storyboard */; };
@@ -104,6 +105,7 @@
 		D11250C01BAC4B6300B986EF /* ImageTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageTransition.swift; sourceTree = "<group>"; };
 		D151E72A1AD3C48D004FD4AE /* UIImage+Decode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Decode.swift"; sourceTree = "<group>"; };
 		D166E4CC1B73820700B129E3 /* UIImage+Normalize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Normalize.swift"; sourceTree = "<group>"; };
+		D1B1B98F1BC7EB7100DE20D8 /* ThreadHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreadHelper.swift; sourceTree = "<group>"; };
 		D1ED2D0B1AD2CFA600CFC3EB /* Kingfisher-Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Kingfisher-Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		D1ED2D0F1AD2CFA600CFC3EB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		D1ED2D101AD2CFA600CFC3EB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -223,6 +225,7 @@
 				D11250C01BAC4B6300B986EF /* ImageTransition.swift */,
 				4B412CA41AE8A2F9008D530A /* KingfisherOptionsInfo.swift */,
 				4B2C4DF71B7D7ACD000912CA /* Resource.swift */,
+				D1B1B98F1BC7EB7100DE20D8 /* ThreadHelper.swift */,
 				D1ED2D371AD2D09F00CFC3EB /* Supporting Files */,
 			);
 			path = Kingfisher;
@@ -479,6 +482,7 @@
 				4B945B211ADBB20200D1545E /* UIButton+Kingfisher.swift in Sources */,
 				D1ED2D5D1AD2D0F900CFC3EB /* ImageCache.swift in Sources */,
 				D1ED2D5E1AD2D0F900CFC3EB /* ImageDownloader.swift in Sources */,
+				D1B1B9901BC7EB7100DE20D8 /* ThreadHelper.swift in Sources */,
 				4B412CA51AE8A2F9008D530A /* KingfisherOptionsInfo.swift in Sources */,
 				4B2C4DF81B7D7ACD000912CA /* Resource.swift in Sources */,
 				D1ED2D601AD2D0F900CFC3EB /* KingfisherOptions.swift in Sources */,

+ 17 - 16
Kingfisher/ImageCache.swift

@@ -261,24 +261,25 @@ extension ImageCache {
     public func retrieveImageForKey(key: String, options:KingfisherManager.Options, completionHandler: ((UIImage?, CacheType!) -> ())?) -> RetrieveImageDiskTask? {
         // No completion handler. Not start working and early return.
         guard let completionHandler = completionHandler else {
-            return dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS) {}
+            return nil
         }
         
-        let block = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS) {
-            if let image = self.retrieveImageInMemoryCacheForKey(key) {
-                
-                //Found image in memory cache.
-                if options.shouldDecode {
-                    dispatch_async(self.processQueue, { () -> Void in
-                        let result = image.kf_decodedImage(scale: options.scale)
-                        dispatch_async(options.queue, { () -> Void in
-                            completionHandler(result, .Memory)
-                        })
+        var block: RetrieveImageDiskTask?
+        if let image = self.retrieveImageInMemoryCacheForKey(key) {
+            
+            //Found image in memory cache.
+            if options.shouldDecode {
+                dispatch_async(self.processQueue, { () -> Void in
+                    let result = image.kf_decodedImage(scale: options.scale)
+                    dispatch_async(options.queue, { () -> Void in
+                        completionHandler(result, .Memory)
                     })
-                } else {
-                    completionHandler(image, .Memory)
-                }
+                })
             } else {
+                completionHandler(image, .Memory)
+            }
+        } else {
+            block = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS) {
                 //Begin to load image from disk
                 dispatch_async(self.ioQueue, { () -> Void in
                     
@@ -308,9 +309,9 @@ extension ImageCache {
                     }
                 })
             }
+            dispatch_async(dispatch_get_main_queue(), block!)
         }
-        
-        dispatch_async(dispatch_get_main_queue(), block)
+    
         return block
     }
     

+ 1 - 1
Kingfisher/Info.plist

@@ -19,7 +19,7 @@
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>265</string>
+	<string>267</string>
 	<key>NSPrincipalClass</key>
 	<string></string>
 </dict>

+ 35 - 0
Kingfisher/ThreadHelper.swift

@@ -0,0 +1,35 @@
+//
+//  ThreadHelper.swift
+//  Kingfisher
+//
+//  Created by Wei Wang on 15/10/9.
+//
+//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+func dispatch_async_safely_main_queue(block: ()->()) {
+    if NSThread.isMainThread() {
+        block()
+    } else {
+        dispatch_async(dispatch_get_main_queue()) {
+            block()
+        }
+    }
+}

+ 17 - 12
Kingfisher/UIButton+Kingfisher.swift

@@ -201,13 +201,16 @@ public extension UIButton {
                     progressBlock(receivedSize: receivedSize, totalSize: totalSize)
                 })
             }
-            }) { (image, error, cacheType, imageURL) -> () in
-                dispatch_async(dispatch_get_main_queue(), { () -> Void in
-                    if (imageURL == self.kf_webURLForState(state) && image != nil) {
-                        self.setImage(image, forState: state)
+            }) {[weak self] (image, error, cacheType, imageURL) -> () in
+                
+                dispatch_async_safely_main_queue {
+                    if let sSelf = self {
+                        if (imageURL == sSelf.kf_webURLForState(state) && image != nil) {
+                            sSelf.setImage(image, forState: state)
+                        }
+                        completionHandler?(image: image, error: error, cacheType: cacheType, imageURL: imageURL)
                     }
-                    completionHandler?(image: image, error: error, cacheType: cacheType, imageURL: imageURL)
-                })
+                }
         }
         
         return task
@@ -448,13 +451,15 @@ public extension UIButton {
                     progressBlock(receivedSize: receivedSize, totalSize: totalSize)
                 })
             }
-            }) { (image, error, cacheType, imageURL) -> () in
-                dispatch_async(dispatch_get_main_queue(), { () -> Void in
-                    if (imageURL == self.kf_backgroundWebURLForState(state) && image != nil) {
-                        self.setBackgroundImage(image, forState: state)
+            }) { [weak self] (image, error, cacheType, imageURL) -> () in
+                dispatch_async_safely_main_queue {
+                    if let sSelf = self {
+                        if (imageURL == sSelf.kf_backgroundWebURLForState(state) && image != nil) {
+                            sSelf.setBackgroundImage(image, forState: state)
+                        }
+                        completionHandler?(image: image, error: error, cacheType: cacheType, imageURL: imageURL)
                     }
-                    completionHandler?(image: image, error: error, cacheType: cacheType, imageURL: imageURL)
-                })
+                }
         }
         
         return task

+ 3 - 2
Kingfisher/UIImageView+Kingfisher.swift

@@ -195,7 +195,8 @@ public extension UIImageView {
                 })
             }
             }, completionHandler: {[weak self] (image, error, cacheType, imageURL) -> () in
-                dispatch_async(dispatch_get_main_queue(), { () -> Void in
+                
+                dispatch_async_safely_main_queue {
                     if let sSelf = self where imageURL == sSelf.kf_webURL && image != nil {
                         if let transition = optionsInfo?[.Transition] as? ImageTransition {
                             UIView.transitionWithView(sSelf, duration: 0.0, options: [], animations: { () -> Void in
@@ -215,7 +216,7 @@ public extension UIImageView {
                     }
                     
                     completionHandler?(image: image, error: error, cacheType: cacheType, imageURL: imageURL)
-                })
+                }
             })
         
         return task