Jelajahi Sumber

Merge pull request #2 from onevcat/master

同步
LEE 6 tahun lalu
induk
melakukan
9fc4c1ad98

+ 1 - 0
.gitignore

@@ -35,6 +35,7 @@ DerivedData
 # Carthage/Checkouts
 
 Carthage/Build
+Kingfisher.framework.zip
 
 # OSX
 .DS_Store

+ 11 - 0
CHANGELOG.md

@@ -2,6 +2,17 @@
 
 -----
 
+## [5.5.0 - Progressive JPEG](https://github.com/onevcat/Kingfisher/releases/tag/5.5.0) (2019-05-17)
+
+#### Add
+* Add support for loading progressive JPEG images. This feature is still in beta and will be improved in the next few releases. To try it out, make sure you are loading a progressive JPEG image with a `.progressiveJPEG` options passed in. Thanks @lixiang1994 [#1181](https://github.com/onevcat/Kingfisher/pull/1181)
+* Choose to use `Swift.Result` as the default result type when Swift 5.0 or above is applied. [#1146](https://github.com/onevcat/Kingfisher/pull/1146)
+
+#### Fix
+* Apply to some modern Swift syntax, which may also improve internal performance a bit. [#1181](https://github.com/onevcat/Kingfisher/pull/1181)
+
+---
+
 ## [5.4.0 - Accio Support](https://github.com/onevcat/Kingfisher/releases/tag/5.4.0) (2019-04-24)
 
 #### Add

+ 12 - 12
Gemfile.lock

@@ -12,10 +12,10 @@ GEM
     atomos (0.1.3)
     babosa (1.0.2)
     claide (1.0.2)
-    cocoapods (1.7.0.beta.3)
+    cocoapods (1.7.0.rc.2)
       activesupport (>= 4.0.2, < 5)
       claide (>= 1.0.2, < 2.0)
-      cocoapods-core (= 1.7.0.beta.3)
+      cocoapods-core (= 1.7.0.rc.2)
       cocoapods-deintegrate (>= 1.0.3, < 2.0)
       cocoapods-downloader (>= 1.2.2, < 2.0)
       cocoapods-plugins (>= 1.0.0, < 2.0)
@@ -31,7 +31,7 @@ GEM
       nap (~> 1.0)
       ruby-macho (~> 1.4)
       xcodeproj (>= 1.8.2, < 2.0)
-    cocoapods-core (1.7.0.beta.3)
+    cocoapods-core (1.7.0.rc.2)
       activesupport (>= 4.0.2, < 6)
       fuzzy_match (~> 2.0.4)
       nap (~> 1.0)
@@ -58,7 +58,7 @@ GEM
     dotenv (2.7.2)
     emoji_regex (1.0.1)
     escape (0.0.4)
-    excon (0.62.0)
+    excon (0.64.0)
     faraday (0.15.4)
       multipart-post (>= 1.2, < 3)
     faraday-cookie_jar (0.0.6)
@@ -67,7 +67,7 @@ GEM
     faraday_middleware (0.13.1)
       faraday (>= 0.7.4, < 1.0)
     fastimage (2.1.5)
-    fastlane (2.119.0)
+    fastlane (2.123.0)
       CFPropertyList (>= 2.3, < 4.0.0)
       addressable (>= 2.3, < 3.0.0)
       babosa (>= 1.0.2, < 2.0.0)
@@ -153,7 +153,7 @@ GEM
     memoist (0.16.0)
     mime-types (3.2.2)
       mime-types-data (~> 3.2015)
-    mime-types-data (3.2018.0812)
+    mime-types-data (3.2019.0331)
     mini_magick (4.5.1)
     minitest (5.11.3)
     molinillo (0.6.6)
@@ -166,7 +166,7 @@ GEM
     naturally (2.2.0)
     netrc (0.11.0)
     open4 (1.3.4)
-    os (1.0.0)
+    os (1.0.1)
     plist (3.5.0)
     public_suffix (2.0.5)
     rb-fsevent (0.10.3)
@@ -181,7 +181,7 @@ GEM
     rouge (2.0.7)
     ruby-macho (1.4.0)
     rubyzip (1.2.2)
-    sass (3.7.3)
+    sass (3.7.4)
       sass-listen (~> 4.0.0)
     sass-listen (4.0.0)
       rb-fsevent (~> 0.9, >= 0.9.4)
@@ -196,7 +196,7 @@ GEM
       CFPropertyList
       naturally
     slack-notifier (2.3.2)
-    sqlite3 (1.4.0)
+    sqlite3 (1.4.1)
     terminal-notifier (2.0.0)
     terminal-table (1.8.0)
       unicode-display_width (~> 1.1, >= 1.1.1)
@@ -210,12 +210,12 @@ GEM
     uber (0.1.0)
     unf (0.1.4)
       unf_ext
-    unf_ext (0.0.7.5)
-    unicode-display_width (1.5.0)
+    unf_ext (0.0.7.6)
+    unicode-display_width (1.6.0)
     word_wrap (1.0.0)
     xcinvoke (0.3.0)
       liferaft (~> 0.0.6)
-    xcodeproj (1.8.2)
+    xcodeproj (1.9.0)
       CFPropertyList (>= 2.3.3, < 4.0)
       atomos (~> 0.1.3)
       claide (>= 1.0.2, < 2.0)

+ 1 - 1
Kingfisher.podspec

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

+ 16 - 16
Kingfisher.xcodeproj/project.pbxproj

@@ -1374,11 +1374,11 @@
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				CODE_SIGN_IDENTITY = "";
 				COMBINE_HIDPI_IMAGES = YES;
-				CURRENT_PROJECT_VERSION = 1615;
+				CURRENT_PROJECT_VERSION = 1652;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
-				DYLIB_CURRENT_VERSION = 1615;
+				DYLIB_CURRENT_VERSION = 1652;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				FRAMEWORK_VERSION = A;
 				GCC_NO_COMMON_BLOCKS = YES;
@@ -1402,11 +1402,11 @@
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				CODE_SIGN_IDENTITY = "";
 				COMBINE_HIDPI_IMAGES = YES;
-				CURRENT_PROJECT_VERSION = 1615;
+				CURRENT_PROJECT_VERSION = 1652;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
-				DYLIB_CURRENT_VERSION = 1615;
+				DYLIB_CURRENT_VERSION = 1652;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				FRAMEWORK_VERSION = A;
 				GCC_NO_COMMON_BLOCKS = YES;
@@ -1503,11 +1503,11 @@
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
-				CURRENT_PROJECT_VERSION = 1615;
+				CURRENT_PROJECT_VERSION = 1652;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
-				DYLIB_CURRENT_VERSION = 1615;
+				DYLIB_CURRENT_VERSION = 1652;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				GCC_NO_COMMON_BLOCKS = YES;
 				INFOPLIST_FILE = Sources/Info.plist;
@@ -1534,11 +1534,11 @@
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
-				CURRENT_PROJECT_VERSION = 1615;
+				CURRENT_PROJECT_VERSION = 1652;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
-				DYLIB_CURRENT_VERSION = 1615;
+				DYLIB_CURRENT_VERSION = 1652;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				GCC_NO_COMMON_BLOCKS = YES;
 				INFOPLIST_FILE = Sources/Info.plist;
@@ -1562,11 +1562,11 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
-				CURRENT_PROJECT_VERSION = 1615;
+				CURRENT_PROJECT_VERSION = 1652;
 				DEBUG_INFORMATION_FORMAT = dwarf;
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
-				DYLIB_CURRENT_VERSION = 1615;
+				DYLIB_CURRENT_VERSION = 1652;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				GCC_NO_COMMON_BLOCKS = YES;
 				INFOPLIST_FILE = Sources/Info.plist;
@@ -1590,11 +1590,11 @@
 			buildSettings = {
 				APPLICATION_EXTENSION_API_ONLY = YES;
 				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
-				CURRENT_PROJECT_VERSION = 1615;
+				CURRENT_PROJECT_VERSION = 1652;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEFINES_MODULE = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1;
-				DYLIB_CURRENT_VERSION = 1615;
+				DYLIB_CURRENT_VERSION = 1652;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				GCC_NO_COMMON_BLOCKS = YES;
 				INFOPLIST_FILE = Sources/Info.plist;
@@ -1734,10 +1734,10 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
 				CODE_SIGN_STYLE = Manual;
-				CURRENT_PROJECT_VERSION = 1615;
+				CURRENT_PROJECT_VERSION = 1652;
 				DEVELOPMENT_TEAM = "";
 				DYLIB_COMPATIBILITY_VERSION = 1;
-				DYLIB_CURRENT_VERSION = 1615;
+				DYLIB_CURRENT_VERSION = 1652;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				INFOPLIST_FILE = Sources/Info.plist;
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@@ -1762,10 +1762,10 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
 				CODE_SIGN_STYLE = Manual;
-				CURRENT_PROJECT_VERSION = 1615;
+				CURRENT_PROJECT_VERSION = 1652;
 				DEVELOPMENT_TEAM = "";
 				DYLIB_COMPATIBILITY_VERSION = 1;
-				DYLIB_CURRENT_VERSION = 1615;
+				DYLIB_CURRENT_VERSION = 1652;
 				DYLIB_INSTALL_NAME_BASE = "@rpath";
 				INFOPLIST_FILE = Sources/Info.plist;
 				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";

+ 2 - 5
Sources/General/KingfisherOptionsInfo.swift

@@ -216,8 +216,6 @@ public enum KingfisherOptionsInfoItem {
     
     /// Enable progressive image loading, Kingfisher will use the `ImageProgressive` of
     case progressiveJPEG(ImageProgressive)
-
-    case onDataReceived([DataReceivingSideEffect])
 }
 
 // Improve performance by parsing the input `KingfisherOptionsInfo` (self) first.
@@ -258,7 +256,7 @@ public struct KingfisherParsedOptionsInfo {
     public var processingQueue: CallbackQueue? = nil
     public var progressiveJPEG: ImageProgressive? = nil
 
-    public var onDataReceived: [DataReceivingSideEffect]? = nil
+    var onDataReceived: [DataReceivingSideEffect]? = nil
     
     public init(_ info: KingfisherOptionsInfo?) {
         guard let info = info else { return }
@@ -295,7 +293,6 @@ public struct KingfisherParsedOptionsInfo {
             case .diskCacheExpiration(let expiration): diskCacheExpiration = expiration
             case .processingQueue(let queue): processingQueue = queue
             case .progressiveJPEG(let value): progressiveJPEG = value
-            case .onDataReceived(let value): onDataReceived = value
             }
         }
 
@@ -315,7 +312,7 @@ extension KingfisherParsedOptionsInfo {
     }
 }
 
-public protocol DataReceivingSideEffect: AnyObject {
+protocol DataReceivingSideEffect: AnyObject {
     var onShouldApply: () -> Bool { get set }
     func onDataReceived(_ session: URLSession, task: SessionDataTask, data: Data)
 }

+ 0 - 74
Sources/Image/ImageDrawing.swift

@@ -527,77 +527,3 @@ extension KingfisherWrapper where Base: Image {
     }
     #endif
 }
-
-extension CGImage: KingfisherCompatible {}
-/// High Performance Image Resizing
-/// @see https://nshipster.com/image-resizing/
-extension KingfisherWrapper where Base: CGImage {
-    var size: CGSize {
-        return CGSize(width: CGFloat(base.width), height: CGFloat(base.height))
-    }
-
-    /// Resizes `base` CGImage to a CGImage of new size, respecting the given content mode.
-    ///
-    /// - Parameters:
-    ///   - targetSize: The target size in point.
-    ///   - contentMode: Content mode of output image should be.
-    /// - Returns: A CGImage with new size.
-    #if os(iOS) || os(tvOS)
-    public func resize(to size: CGSize, for contentMode: UIView.ContentMode) -> CGImage {
-        switch contentMode {
-        case .scaleAspectFit:
-            return resize(to: size, for: .aspectFit)
-        case .scaleAspectFill:
-            return resize(to: size, for: .aspectFill)
-        default:
-            return resize(to: size)
-        }
-    }
-    #endif
-
-    // MARK: - Resize
-    /// Resizes `base` CGImage to a CGImage with new size.
-    ///
-    /// - Parameter size: The target size in point.
-    /// - Returns: A CGImage with new size.
-    public func resize(to size: CGSize) -> CGImage {
-        let alphaInfo = base.alphaInfo.rawValue & CGBitmapInfo.alphaInfoMask.rawValue
-        var hasAlpha = false
-        if alphaInfo == CGImageAlphaInfo.premultipliedLast.rawValue
-            || alphaInfo == CGImageAlphaInfo.premultipliedFirst.rawValue
-            || alphaInfo == CGImageAlphaInfo.first.rawValue
-            || alphaInfo == CGImageAlphaInfo.last.rawValue {
-            hasAlpha = true
-        }
-
-        var bitmapInfo = CGImageByteOrderInfo.order32Little.rawValue
-        bitmapInfo |= hasAlpha ? CGImageAlphaInfo.premultipliedFirst.rawValue : CGImageAlphaInfo.noneSkipFirst.rawValue
-
-        guard let context = CGContext(data: nil,
-                                      width: Int(size.width),
-                                      height: Int(size.height),
-                                      bitsPerComponent: base.bitsPerComponent,
-                                      bytesPerRow: base.bytesPerRow,
-                                      space: base.colorSpace ?? CGColorSpaceCreateDeviceRGB(),
-                                      bitmapInfo: bitmapInfo) else
-        {
-            return base
-        }
-
-        let rect = CGRect(origin: .zero, size: size)
-        context.interpolationQuality = .high
-        context.draw(base, in: rect)
-        return context.makeImage() ?? base
-    }
-
-    /// Resizes `base` CGImage to a CGImage of new size, respecting the given content mode.
-    ///
-    /// - Parameters:
-    ///   - targetSize: The target size in point.
-    ///   - contentMode: Content mode of output image should be.
-    /// - Returns: A CGImage with new size.
-    public func resize(to targetSize: CGSize, for contentMode: ContentMode) -> CGImage {
-        let newSize = size.kf.resize(to: targetSize, for: contentMode)
-        return resize(to: newSize)
-    }
-}

+ 2 - 2
Sources/Info.plist

@@ -15,11 +15,11 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>5.4.0</string>
+	<string>5.5.0</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>1615</string>
+	<string>1652</string>
 	<key>NSPrincipalClass</key>
 	<string></string>
 </dict>

+ 4 - 0
Sources/Utility/Result.swift

@@ -26,6 +26,9 @@
 
 import Foundation
 
+#if swift(>=4.3)
+/// Result type already built-in
+#else
 /// A value that represents either a success or failure, capturing associated
 /// values in both cases.
 public enum Result<Success, Failure> {
@@ -189,6 +192,7 @@ extension Result : CustomDebugStringConvertible {
         return output
     }
 }
+#endif
 
 // Deprecated
 extension Result {

+ 21 - 9
Sources/Views/AnimatedImageView.swift

@@ -120,6 +120,10 @@ open class AnimatedImageView: UIImageView {
     /// Default is `true`.
     public var needsPrescaling = true
 
+    /// Decode the GIF frames in background thread before using. It will decode frames data and do a off-screen
+    /// rendering to extract pixel information in background. This can reduce the main thread CPU usage.
+    public var backgroundDecode = true
+
     /// The animation timer's run loop mode. Default is `RunLoop.Mode.common`.
     /// Set this property to `RunLoop.Mode.default` will make the animation pause during UIScrollView scrolling.
     public var runLoopMode = KFRunLoopModeCommon {
@@ -251,6 +255,7 @@ open class AnimatedImageView: UIImageView {
                 preloadQueue: preloadQueue)
             animator.delegate = self
             animator.needsPrescaling = needsPrescaling
+            animator.backgroundDecode = backgroundDecode
             animator.prepareFramesAsynchronously()
             self.animator = animator
         }
@@ -361,6 +366,9 @@ extension AnimatedImageView {
         var isFinished: Bool = false
 
         var needsPrescaling = true
+
+        var backgroundDecode = true
+
         weak var delegate: AnimatorDelegate?
 
         // Total duration of one animation loop
@@ -488,18 +496,22 @@ extension AnimatedImageView {
         }
 
         private func loadFrame(at index: Int) -> UIImage? {
-            guard let image = CGImageSourceCreateImageAtIndex(imageSource, index, nil) else {
+            let options: [CFString: Any] = [
+                kCGImageSourceCreateThumbnailFromImageIfAbsent: true,
+                kCGImageSourceCreateThumbnailWithTransform: true,
+                kCGImageSourceShouldCacheImmediately: true,
+                kCGImageSourceThumbnailMaxPixelSize: max(size.width, size.height)
+            ]
+
+            let resize = needsPrescaling && size != .zero
+            guard let cgImage = CGImageSourceCreateImageAtIndex(imageSource,
+                                                                index,
+                                                                resize ? options as CFDictionary : nil) else {
                 return nil
             }
 
-            let scaledImage: CGImage
-            if needsPrescaling, size != .zero {
-                scaledImage = image.kf.resize(to: size, for: contentMode)
-            } else {
-                scaledImage = image
-            }
-
-            return Image(cgImage: scaledImage)
+            let image = Image(cgImage: cgImage)
+            return backgroundDecode ? image.kf.decoded : image
         }
         
         private func updatePreloadedFrames() {

+ 2 - 2
Tests/KingfisherTests-macOS/Info.plist

@@ -15,10 +15,10 @@
 	<key>CFBundlePackageType</key>
 	<string>BNDL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>5.4.0</string>
+	<string>5.5.0</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>1615</string>
+	<string>1652</string>
 </dict>
 </plist>

+ 2 - 2
Tests/KingfisherTests-tvOS/Info.plist

@@ -15,10 +15,10 @@
 	<key>CFBundlePackageType</key>
 	<string>BNDL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>5.4.0</string>
+	<string>5.5.0</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>1615</string>
+	<string>1652</string>
 </dict>
 </plist>

+ 4 - 4
Tests/KingfisherTests/DataReceivingSideEffectTests.swift

@@ -59,14 +59,14 @@ class DataReceivingSideEffectTests: XCTestCase {
         super.tearDown()
     }
 
-    func testDataReceivingSideEffectBlockCanBeCalled() {
+    func xtestDataReceivingSideEffectBlockCanBeCalled() {
         let exp = expectation(description: #function)
         let url = testURLs[0]
         stub(url, data: testImageData, length: 123)
 
         let receiver = DataReceivingStub()
 
-        let options: KingfisherOptionsInfo = [.onDataReceived([receiver]), .waitForCache]
+        let options: KingfisherOptionsInfo = [/*.onDataReceived([receiver]),*/ .waitForCache]
         KingfisherManager.shared.retrieveImage(with: url, options: options) {
             result in
             XCTAssertTrue(receiver.called)
@@ -75,14 +75,14 @@ class DataReceivingSideEffectTests: XCTestCase {
         waitForExpectations(timeout: 3, handler: nil)
     }
 
-    func testDataReceivingSideEffectBlockCanBeCalledButNotApply() {
+    func xtestDataReceivingSideEffectBlockCanBeCalledButNotApply() {
         let exp = expectation(description: #function)
         let url = testURLs[0]
         stub(url, data: testImageData, length: 123)
 
         let receiver = DataReceivingNotAppyStub()
 
-        let options: KingfisherOptionsInfo = [.onDataReceived([receiver]), .waitForCache]
+        let options: KingfisherOptionsInfo = [/*.onDataReceived([receiver]),*/ .waitForCache]
         KingfisherManager.shared.retrieveImage(with: url, options: options) {
             result in
             XCTAssertTrue(receiver.called)

+ 2 - 2
Tests/KingfisherTests/Info.plist

@@ -15,10 +15,10 @@
 	<key>CFBundlePackageType</key>
 	<string>BNDL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>5.4.0</string>
+	<string>5.5.0</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>1615</string>
+	<string>1652</string>
 </dict>
 </plist>

+ 3 - 1
fastlane/Fastfile

@@ -51,6 +51,7 @@ platform :ios do
       
       tests
       lint
+      carthage(command: "archive", frameworks: ["Kingfisher"])
       
       sync_build_number_to_git
       increment_version_number(version_number: target_version)
@@ -72,7 +73,8 @@ platform :ios do
       api_token: ENV['GITHUB_TOKEN'],
       name: release_log[:title],
       tag_name: target_version,
-      description: release_log[:text]
+      description: release_log[:text],
+      upload_assets: ["Kingfisher.framework.zip"]
       )
 
       pod_push