wenweiwei 3 gadi atpakaļ
vecāks
revīzija
778b8f2e4b
60 mainītis faili ar 1726 papildinājumiem un 8975 dzēšanām
  1. 17 17
      BFFramework/Classes/Utils/PQThirdPlatformUtil.swift
  2. 4 4
      Example/BFFramework.xcodeproj/project.pbxproj
  3. 1 1
      Example/Pods/Kingfisher/LICENSE
  4. 184 60
      Example/Pods/Kingfisher/README.md
  5. 0 503
      Example/Pods/Kingfisher/Sources/AnimatedImageView.swift
  6. 0 34
      Example/Pods/Kingfisher/Sources/Box.swift
  7. 0 87
      Example/Pods/Kingfisher/Sources/CacheSerializer.swift
  8. 0 144
      Example/Pods/Kingfisher/Sources/Filter.swift
  9. 0 96
      Example/Pods/Kingfisher/Sources/FormatIndicatedCacheSerializer.swift
  10. 0 1045
      Example/Pods/Kingfisher/Sources/Image.swift
  11. 0 742
      Example/Pods/Kingfisher/Sources/ImageCache.swift
  12. 0 677
      Example/Pods/Kingfisher/Sources/ImageDownloader.swift
  13. 0 191
      Example/Pods/Kingfisher/Sources/ImageModifier.swift
  14. 0 277
      Example/Pods/Kingfisher/Sources/ImagePrefetcher.swift
  15. 0 713
      Example/Pods/Kingfisher/Sources/ImageProcessor.swift
  16. 0 128
      Example/Pods/Kingfisher/Sources/ImageTransition.swift
  17. 0 263
      Example/Pods/Kingfisher/Sources/ImageView+Kingfisher.swift
  18. 0 203
      Example/Pods/Kingfisher/Sources/Indicator.swift
  19. 0 37
      Example/Pods/Kingfisher/Sources/Kingfisher.h
  20. 0 77
      Example/Pods/Kingfisher/Sources/Kingfisher.swift
  21. 0 297
      Example/Pods/Kingfisher/Sources/KingfisherManager.swift
  22. 0 364
      Example/Pods/Kingfisher/Sources/KingfisherOptionsInfo.swift
  23. 0 82
      Example/Pods/Kingfisher/Sources/Placeholder.swift
  24. 0 53
      Example/Pods/Kingfisher/Sources/RequestModifier.swift
  25. 0 74
      Example/Pods/Kingfisher/Sources/Resource.swift
  26. 0 285
      Example/Pods/Kingfisher/Sources/String+MD5.swift
  27. 0 40
      Example/Pods/Kingfisher/Sources/ThreadHelper.swift
  28. 0 274
      Example/Pods/Kingfisher/Sources/UIButton+Kingfisher.swift
  29. 0 28
      Example/Pods/KingfisherWebP/KingfisherWebP/Classes/CGImage+WebP.h
  30. 0 447
      Example/Pods/KingfisherWebP/KingfisherWebP/Classes/CGImage+WebP.m
  31. 0 88
      Example/Pods/KingfisherWebP/KingfisherWebP/Classes/Image+WebP.swift
  32. 0 16
      Example/Pods/KingfisherWebP/KingfisherWebP/Classes/KingfisherWebP-umbrella.h
  33. 0 32
      Example/Pods/KingfisherWebP/KingfisherWebP/Classes/WebPProcessor.swift
  34. 0 27
      Example/Pods/KingfisherWebP/KingfisherWebP/Classes/WebPSerializer.swift
  35. 0 10
      Example/Pods/KingfisherWebP/KingfisherWebP/KingfisherWebP.modulemap
  36. 41 4
      Example/Pods/KingfisherWebP/README.md
  37. 9 8
      Example/Pods/Local Podspecs/BFFramework.podspec.json
  38. 5 1
      Example/Pods/Manifest.lock
  39. 1430 1383
      Example/Pods/Pods.xcodeproj/project.pbxproj
  40. 1 1
      Example/Pods/Target Support Files/BFFramework/BFFramework-Info.plist
  41. 2 2
      Example/Pods/Target Support Files/BFFramework/BFFramework-umbrella.h
  42. 2 1
      Example/Pods/Target Support Files/BFFramework/BFFramework.debug.xcconfig
  43. 2 1
      Example/Pods/Target Support Files/BFFramework/BFFramework.release.xcconfig
  44. 1 1
      Example/Pods/Target Support Files/BFFramework/ResourceBundle-BFFramework-BFFramework-Info.plist
  45. 1 1
      Example/Pods/Target Support Files/Kingfisher/Kingfisher-Info.plist
  46. 0 1
      Example/Pods/Target Support Files/Kingfisher/Kingfisher-umbrella.h
  47. 1 1
      Example/Pods/Target Support Files/Kingfisher/Kingfisher.debug.xcconfig
  48. 1 1
      Example/Pods/Target Support Files/Kingfisher/Kingfisher.release.xcconfig
  49. 0 26
      Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift-Info.plist
  50. 0 5
      Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift-dummy.m
  51. 0 12
      Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift-prefix.pch
  52. 0 16
      Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift-umbrella.h
  53. 0 12
      Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift.debug.xcconfig
  54. 0 6
      Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift.modulemap
  55. 0 12
      Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift.release.xcconfig
  56. 6 24
      Example/Pods/Target Support Files/Pods-BFFramework_Example/Pods-BFFramework_Example-acknowledgements.markdown
  57. 12 30
      Example/Pods/Target Support Files/Pods-BFFramework_Example/Pods-BFFramework_Example-acknowledgements.plist
  58. 0 2
      Example/Pods/Target Support Files/Pods-BFFramework_Example/Pods-BFFramework_Example-frameworks.sh
  59. 3 4
      Example/Pods/Target Support Files/Pods-BFFramework_Example/Pods-BFFramework_Example.debug.xcconfig
  60. 3 4
      Example/Pods/Target Support Files/Pods-BFFramework_Example/Pods-BFFramework_Example.release.xcconfig

+ 17 - 17
BFFramework/Classes/Utils/PQThirdPlatformUtil.swift

@@ -11,22 +11,20 @@ import UIKit
 import UserNotifications
 import WechatOpenSDK
 
-
-
 // MARK: - Bugly初始化工具类
+
 public class PQSingletoBuglyUtil: NSObject {
     public static let shared = PQSingletoBuglyUtil()
-    
-    public func registerBugly(appID:String) {
- 
-         let versionName = "\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] ?? "1.0.0")"
-        
+
+    public func registerBugly(appID: String) {
+        let versionName = "\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] ?? "1.0.0")"
+
         // 注册bugly
         let buglyConfig = BuglyConfig()
         buglyConfig.reportLogLevel = .warn
         #if DEBUG
             buglyConfig.version = versionName + ".6666"
-          
+
         #else
             if PQENVUtil.shared.envMode == .ENVModeOnline {
                 buglyConfig.version = versionName + "." + versionCode
@@ -47,6 +45,7 @@ public class PQSingletoBuglyUtil: NSObject {
 }
 
 // MARK: - 微信相关工具类
+
 // 初始化微信要使用的参数 e.g.
 /*
      let state: String = "com.piaoquan.pqspeed"
@@ -62,6 +61,7 @@ public class WXApiInfo: NSObject {
     public var universalLink: String = ""
     public var scope = ""
 }
+
 public class PQSingletoWXApiUtil: NSObject {
     public static let shared = PQSingletoWXApiUtil()
     var openId: String? // openID
@@ -133,7 +133,7 @@ public class PQSingletoWXApiUtil: NSObject {
         let message = WXMediaMessage()
         message.title = title ?? ""
         message.description = description ?? ""
- 
+
         ImageDownloader.default.downloadImage(with: URL(string: imageUrl ?? "")!, options: nil) { result in
             switch result {
             case let .success(imageResult):
@@ -142,24 +142,24 @@ public class PQSingletoWXApiUtil: NSObject {
                     let wxMiniObject = WXMiniProgramObject()
                     wxMiniObject.miniProgramType = PQENVUtil.shared.envMode == .ENVModeOnline ? .release : .test
                     wxMiniObject.userName = shareWeappRawId ?? cShareWeappRawId
-                    var preParams: String = ""
-                    var page: String = ""
+                    var homePagePath: String = ""
+                    var targetPagePath: String = ""
                     var isRhythmVideo = 0
                     if type == 3 {
-                        preParams = "package-point/show/show"
-                        page = "pages/post/post"
+                        homePagePath = "pages/post/post"
+                        targetPagePath = "package-point/show/show"
                         isRhythmVideo = 1
                     } else {
-                        preParams = "user-videos"
-                        page = "pages/category"
+                        homePagePath = "pages/category"
+                        targetPagePath = "user-videos"
                         isRhythmVideo = 0
                     }
-                    var params = (preParams + "?id=\(videoId)&tp=share&rootPageSource=\(pageSource.rawValue)&shareDepth=1&rootLaunchShareId=\(shareId)&parentShareId=\(shareId)&shareId=\(shareId)&shareAppType=13&mid=\(getMachineCode())&su=\(BFLoginUserInfo.shared.uid)&isRhythmVideo=\(isRhythmVideo)").addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
+                    var params = (targetPagePath + "?id=\(videoId)&tp=share&rootPageSource=\(pageSource.rawValue)&shareDepth=1&rootLaunchShareId=\(shareId)&parentShareId=\(shareId)&shareId=\(shareId)&shareAppType=\(PQBFConfig.shared.appType)&mid=\(getMachineCode())&su=\(BFLoginUserInfo.shared.uid)&isRhythmVideo=\(isRhythmVideo)").addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
                     ["/", "=", "?", "&"].forEach { char in
                         let custom = CharacterSet(charactersIn: char).inverted
                         params = params?.addingPercentEncoding(withAllowedCharacters: custom) ?? ""
                     }
-                    wxMiniObject.path = "\(page)?jumpPage=" + (params ?? "")
+                    wxMiniObject.path = "\(homePagePath)?jumpPage=" + (params ?? "")
                     wxMiniObject.webpageUrl = "https://piaoquan.yishihui.com/"
                     wxMiniObject.hdImageData = message.thumbData
                     message.mediaObject = wxMiniObject

+ 4 - 4
Example/BFFramework.xcodeproj/project.pbxproj

@@ -144,8 +144,8 @@
 				607FACCC1AFB9204008FA782 /* Sources */,
 				607FACCD1AFB9204008FA782 /* Frameworks */,
 				607FACCE1AFB9204008FA782 /* Resources */,
-				4891C51BEE84B7DFFA829FAD /* [CP] Embed Pods Frameworks */,
-				21CEA0AE7A716A91F00E718F /* [CP] Copy Pods Resources */,
+				9F3A3F4FAFB7ECE85C8992D1 /* [CP] Embed Pods Frameworks */,
+				1DB36BDEEA2A85B996B807D0 /* [CP] Copy Pods Resources */,
 			);
 			buildRules = (
 			);
@@ -226,7 +226,7 @@
 			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
-		21CEA0AE7A716A91F00E718F /* [CP] Copy Pods Resources */ = {
+		1DB36BDEEA2A85B996B807D0 /* [CP] Copy Pods Resources */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
@@ -244,7 +244,7 @@
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-BFFramework_Example/Pods-BFFramework_Example-resources.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
-		4891C51BEE84B7DFFA829FAD /* [CP] Embed Pods Frameworks */ = {
+		9F3A3F4FAFB7ECE85C8992D1 /* [CP] Embed Pods Frameworks */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (

+ 1 - 1
Example/Pods/Kingfisher/LICENSE

@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2018 Wei Wang
+Copyright (c) 2019 Wei Wang
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal

+ 184 - 60
Example/Pods/Kingfisher/README.md

@@ -1,116 +1,240 @@
 <p align="center">
-
 <img src="https://raw.githubusercontent.com/onevcat/Kingfisher/master/images/logo.png" alt="Kingfisher" title="Kingfisher" width="557"/>
-
 </p>
 
 <p align="center">
-<a href="https://travis-ci.org/onevcat/Kingfisher"><img src="https://img.shields.io/travis/onevcat/Kingfisher/master.svg"></a>
+<a href="https://github.com/onevcat/Kingfisher/actions?query=workflow%3Abuild"><img src="https://github.com/onevcat/kingfisher/workflows/build/badge.svg?branch=master"></a>
+<a href="https://kingfisher.onevcat.com/"><img src="https://img.shields.io/badge/Swift-Doc-DE5C43.svg?style=flat"></a>
+<a href="https://cocoapods.org/pods/Kingfisher"><img src="https://img.shields.io/cocoapods/v/Kingfisher.svg?style=flat"></a>
 <a href="https://github.com/Carthage/Carthage/"><img src="https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat"></a>
-<a href="http://onevcat.github.io/Kingfisher/"><img src="https://img.shields.io/cocoapods/v/Kingfisher.svg?style=flat"></a>
+<a href="https://swift.org/package-manager/"><img src="https://img.shields.io/badge/SPM-supported-DE5C43.svg?style=flat"></a>
+<br />
 <a href="https://raw.githubusercontent.com/onevcat/Kingfisher/master/LICENSE"><img src="https://img.shields.io/cocoapods/l/Kingfisher.svg?style=flat"></a>
-<a href="http://onevcat.github.io/Kingfisher/"><img src="https://img.shields.io/cocoapods/p/Kingfisher.svg?style=flat"></a>
-<a href="https://codebeat.co/projects/github-com-onevcat-kingfisher"><img alt="codebeat badge" src="https://codebeat.co/assets/svg/badges/A-398b39-669406e9e1b136187b91af587d4092b0160370f271f66a651f444b990c2730e9.svg" /></a>
-<a href="#backers" alt="sponsors on Open Collective"><img src="https://opencollective.com/Kingfisher/backers/badge.svg" /></a>
-<a href="#sponsors" alt="Sponsors on Open Collective"><img src="https://opencollective.com/Kingfisher/sponsors/badge.svg" /></a>
+<a href="https://kingfisher.onevcat.com/"><img src="https://img.shields.io/cocoapods/p/Kingfisher.svg?style=flat"></a>
 </p>
 
-Kingfisher is a lightweight, pure-Swift library for downloading and caching images from the web. This project is heavily inspired by the popular [SDWebImage](https://github.com/rs/SDWebImage). It provides you a chance to use a pure-Swift alternative in your next app.
+Kingfisher is a powerful, pure-Swift library for downloading and caching images from the web. It provides you a chance to use a pure-Swift way to work with remote images in your next app.
 
 ## Features
 
 - [x] Asynchronous image downloading and caching.
-- [x] `URLSession`-based networking. Basic image processors and filters supplied.
-- [x] Multiple-layer cache for both memory and disk.
-- [x] Cancelable downloading and processing tasks to improve performance.
-- [x] Independent components. Use the downloader or caching system separately as you need.
-- [x] Prefetching images and showing them from cache later when necessary.
-- [x] Extensions for `UIImageView`, `NSImage` and `UIButton` to directly set an image from a URL.
+- [x] Loading image from either `URLSession`-based networking or local provided data.
+- [x] Useful image processors and filters provided.
+- [x] Multiple-layer hybrid cache for both memory and disk.
+- [x] Fine control on cache behavior. Customizable expiration date and size limit.
+- [x] Cancelable downloading and auto-reusing previous downloaded content to improve performance.
+- [x] Independent components. Use the downloader, caching system, and image processors separately as you need.
+- [x] Prefetching images and showing them from the cache to boost your app.
+- [x] View extensions for `UIImageView`, `NSImageView`, `NSButton` and `UIButton` to directly set an image from a URL.
 - [x] Built-in transition animation when setting images.
-- [x] Customizable placeholder while loading images.
-- [x] Extensible image processing and image format support.
+- [x] Customizable placeholder and indicator while loading images.
+- [x] Extensible image processing and image format easily.
+- [x] Low Data Mode support.
+- [x] SwiftUI support.
+
+### Kingfisher 101
 
 The simplest use-case is setting an image to an image view with the `UIImageView` extension:
 
 ```swift
-let url = URL(string: "url_of_your_image")
+import Kingfisher
+
+let url = URL(string: "https://example.com/image.png")
 imageView.kf.setImage(with: url)
 ```
 
-Kingfisher will download the image from `url`, send it to both the memory cache and the disk cache, and display it in `imageView`. When you use the same code later, the image will be retrieved from cache and shown immediately.
+Kingfisher will download the image from `url`, send it to both memory cache and disk cache, and display it in `imageView`. 
+When you set with the same URL later, the image will be retrieved from the cache and shown immediately.
+
+It also works if you use SwiftUI:
+
+```swift
+var body: some View {
+    KFImage(URL(string: "https://example.com/image.png")!)
+}
+```
+
+### A More Advanced Example
+
+With the powerful options, you can do hard tasks with Kingfisher in a simple way. For example, the code below: 
+
+1. Downloads a high-resolution image.
+2. Downsamples it to match the image view size.
+3. Makes it round cornered with a given radius.
+4. Shows a system indicator and a placeholder image while downloading.
+5. When prepared, it animates the small thumbnail image with a "fade in" effect. 
+6. The original large image is also cached to disk for later use, to get rid of downloading it again in a detail view.
+7. A console log is printed when the task finishes, either for success or failure.
+
+```swift
+let url = URL(string: "https://example.com/high_resolution_image.png")
+let processor = DownsamplingImageProcessor(size: imageView.bounds.size)
+             |> RoundCornerImageProcessor(cornerRadius: 20)
+imageView.kf.indicatorType = .activity
+imageView.kf.setImage(
+    with: url,
+    placeholder: UIImage(named: "placeholderImage"),
+    options: [
+        .processor(processor),
+        .scaleFactor(UIScreen.main.scale),
+        .transition(.fade(1)),
+        .cacheOriginalImage
+    ])
+{
+    result in
+    switch result {
+    case .success(let value):
+        print("Task done for: \(value.source.url?.absoluteString ?? "")")
+    case .failure(let error):
+        print("Job failed: \(error.localizedDescription)")
+    }
+}
+```
+
+It is a common situation I can meet in my daily work. Think about how many lines you need to write without
+Kingfisher!
+
+### Method Chaining
+
+If you are not a fan of the `kf` extension, you can also prefer to use the `KF` builder and chained the method 
+invocations. The code below is doing the same thing:
+
+```swift
+// Use `kf` extension
+imageView.kf.setImage(
+    with: url,
+    placeholder: placeholderImage,
+    options: [
+        .processor(processor),
+        .loadDiskFileSynchronously,
+        .cacheOriginalImage,
+        .transition(.fade(0.25)),
+        .lowDataMode(.network(lowResolutionURL))
+    ],
+    progressBlock: { receivedSize, totalSize in
+        // Progress updated
+    },
+    completionHandler: { result in
+        // Done
+    }
+)
+
+// Use `KF` builder
+KF.url(url)
+  .placeholder(placeholderImage)
+  .setProcessor(processor)
+  .loadDiskFileSynchronously()
+  .cacheMemoryOnly()
+  .fade(duration: 0.25)
+  .lowDataModeSource(.network(lowResolutionURL))
+  .onProgress { receivedSize, totalSize in  }
+  .onSuccess { result in  }
+  .onFailure { error in }
+  .set(to: imageView)
+```
+
+And even better, if later you want to switch to SwiftUI, just make some trivial changes and you've done.
+
+```swift
+struct ContentView: View {
+    var body: some View {
+        KFImage.url(url)
+          .placeholder(placeholderImage)
+          .setProcessor(processor)
+          .loadDiskFileSynchronously()
+          .cacheMemoryOnly()
+          .fade(duration: 0.25)
+          .lowDataModeSource(.network(lowResolutionURL))
+          .onProgress { receivedSize, totalSize in  }
+          .onSuccess { result in  }
+          .onFailure { error in }
+    }
+}
+```
+
+### Learn More
 
-For more examples of using Kingfisher, take a look at the [Cheat Sheet](https://github.com/onevcat/Kingfisher/wiki/Cheat-Sheet).
+To learn the use of Kingfisher by more examples, take a look at the well-prepared [Cheat Sheet](https://github.com/onevcat/Kingfisher/wiki/Cheat-Sheet). T
+here we summarized the most common tasks in Kingfisher, you can get a better idea of what this framework can do. 
+There are also some performance tips, remember to check them too.
 
 ## Requirements
 
-- iOS 8.0+ / macOS 10.10+ / tvOS 9.0+ / watchOS 2.0+
-- Swift 4 (Kingfisher 4.x), Swift 3 (Kingfisher 3.x)
+- iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+
+- Swift 4.0+
 
-Main development of Kingfisher is based on Swift 4. Only critical bug fixes will be applied to Kingfisher 3.x.
+### Installation
 
-- Kingfisher 4.0 Migration - Kingfisher 3.x should be source compatible to Kingfisher 4. The reason for a major update is that we need to specify the Swift version explicitly for Xcode. All deprecated methods in Kingfisher 3 has been removed, so please ensure you have no warning left before you migrate from Kingfisher 3 to Kingfisher 4. If you have any trouble in migrating, please open an issue to discuss.
-- [Kingfisher 3.0 Migration Guide](https://github.com/onevcat/Kingfisher/wiki/Kingfisher-3.0-Migration-Guide) - If you are upgrading to Kingfisher 3.x from an earlier version, please read this for more information.
+A detailed guide for installation can be found in [Installation Guide](https://github.com/onevcat/Kingfisher/wiki/Installation-Guide).
 
-## Next Steps
+#### Swift Package Manager
 
-We prepared a [wiki page](https://github.com/onevcat/Kingfisher/wiki). You can find tons of useful things there.
+- File > Swift Packages > Add Package Dependency
+- Add `https://github.com/onevcat/Kingfisher.git`
+- Select "Up to Next Major" with "6.0.0"
 
-* [Installation Guide](https://github.com/onevcat/Kingfisher/wiki/Installation-Guide) - Follow it to integrate Kingfisher into your project.
-* [Cheat Sheet](https://github.com/onevcat/Kingfisher/wiki/Cheat-Sheet)- Curious about what Kingfisher could do and how would it look like when used in your project? See this page for useful code snippets. If you are already familiar with Kingfisher, you could also learn new tricks to improve the way you use Kingfisher! 
-* [API Reference](http://onevcat.github.io/Kingfisher/) - Lastly, please remember to read the full whenever you may need a more detailed reference.
+#### CocoaPods
 
-## Other
+```ruby
+source 'https://github.com/CocoaPods/Specs.git'
+platform :ios, '10.0'
+use_frameworks!
 
-### Future of Kingfisher
+target 'MyApp' do
+  pod 'Kingfisher', '~> 6.0'
+end
+```
 
-I want to keep Kingfisher lightweight. This framework will focus on providing a simple solution for downloading and caching images. This doesn’t mean the framework can’t be improved. Kingfisher is far from perfect, so necessary and useful updates will be made to make it better.
+#### Carthage
 
-### Developments and Tests
+```
+github "onevcat/Kingfisher" ~> 6.0
+```
 
-Any contributing and pull requests are warmly welcome. However, before you plan to implement some features or try to fix an uncertain issue, it is recommended to open a discussion first. 
 
-The test images are contained in another project to keep this project repo fast and slim. You could run `./setup.sh` in the root folder of Kingfisher to clone the test images when you need to run the tests target. It would be appreciated if your pull requests could build and with all tests green. :)
+### Migrating
 
-### About the logo
+[Kingfisher 6.0 Migration](https://github.com/onevcat/Kingfisher/wiki/Kingfisher-6.0-Migration-Guide) - Kingfisher 6.x is NOT fully compatible with the previous version. However, the migration is not difficult. Depending on your use cases, it may take no effect or several minutes to modify your existing code for the new version. Please follow the [migration guide](https://github.com/onevcat/Kingfisher/wiki/Kingfisher-6.0-Migration-Guide) when you prepare to upgrade Kingfisher in your project.
 
-The logo of Kingfisher is inspired by [Tangram (七巧板)](http://en.wikipedia.org/wiki/Tangram), a dissection puzzle consisting of seven flat shapes from China. I believe she's a kingfisher bird instead of a swift, but someone insists that she is a pigeon. I guess I should give her a name. Hi, guys, do you have any suggestions?
+If you are using an even earlier version, see the guides below to know the steps for migrating.
 
-### Contact
+> - [Kingfisher 5.0 Migration](https://github.com/onevcat/Kingfisher/wiki/Kingfisher-5.0-Migration-Guide) - If you are upgrading to Kingfisher 5.x from 4.x, please read this for more information.
+> - Kingfisher 4.0 Migration - Kingfisher 3.x should be source compatible to Kingfisher 4. The reason for a major update is that we need to specify the Swift version explicitly for Xcode. All deprecated methods in Kingfisher 3 were removed, so please ensure you have no warning left before you migrate from Kingfisher 3 to Kingfisher 4. If you have any trouble when migrating, please open an issue to discuss.
+> - [Kingfisher 3.0 Migration](https://github.com/onevcat/Kingfisher/wiki/Kingfisher-3.0-Migration-Guide) - If you are upgrading to Kingfisher 3.x from an earlier version, please read this for more information.
 
-Follow and contact me on [Twitter](http://twitter.com/onevcat) or [Sina Weibo](http://weibo.com/onevcat). If you find an issue, just [open a ticket](https://github.com/onevcat/Kingfisher/issues/new). Pull requests are warmly welcome as well.
+## Next Steps
 
-## Contributors
+We prepared a [wiki page](https://github.com/onevcat/Kingfisher/wiki). You can find tons of useful things there.
+
+* [Installation Guide](https://github.com/onevcat/Kingfisher/wiki/Installation-Guide) - Follow it to integrate Kingfisher into your project.
+* [Cheat Sheet](https://github.com/onevcat/Kingfisher/wiki/Cheat-Sheet)- Curious about what Kingfisher could do and how would it look like when used in your project? See this page for useful code snippets. If you are already familiar with Kingfisher, you could also learn new tricks to improve the way you use Kingfisher!
+* [API Reference](https://kingfisher.onevcat.com/) - Lastly, please remember to read the full whenever you may need a more detailed reference.
 
-This project exists thanks to all the people who contribute. [[Contribute]](https://github.com/onevcat/Kingfisher/blob/master/CONTRIBUTING.md).
-<a href="https://github.com/onevcat/Kingfisher/graphs/contributors"><img src="https://opencollective.com/kingfisher/contributors.svg?width=890" /></a>
+## Other
+
+### Future of Kingfisher
 
+I want to keep Kingfisher lightweight. This framework focuses on providing a simple solution for downloading and caching images. This doesn’t mean the framework can’t be improved. Kingfisher is far from perfect, so necessary and useful updates will be made to make it better.
 
-## Backers
+### Developments and Tests
 
-Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/kingfisher#backer)]
+Any contributing and pull requests are warmly welcome. However, before you plan to implement some features or try to fix an uncertain issue, it is recommended to open a discussion first. It would be appreciated if your pull requests could build and with all tests green. :)
 
-<a href="https://opencollective.com/kingfisher#backers" target="_blank"><img src="https://opencollective.com/kingfisher/backers.svg?width=890"></a>
+### About the logo
 
+The logo of Kingfisher is inspired by [Tangram (七巧板)](http://en.wikipedia.org/wiki/Tangram), a dissection puzzle consisting of seven flat shapes from China. I believe she's a kingfisher bird instead of a swift, but someone insists that she is a pigeon. I guess I should give her a name. Hi, guys, do you have any suggestions?
 
-## Sponsors
+### Contact
 
-Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/kingfisher#sponsor)]
+Follow and contact me on [Twitter](http://twitter.com/onevcat) or [Sina Weibo](http://weibo.com/onevcat). If you find an issue, [open a ticket](https://github.com/onevcat/Kingfisher/issues/new). Pull requests are warmly welcome as well.
 
-<a href="https://opencollective.com/kingfisher/sponsor/0/website" target="_blank"><img src="https://opencollective.com/kingfisher/sponsor/0/avatar.svg"></a>
-<a href="https://opencollective.com/kingfisher/sponsor/1/website" target="_blank"><img src="https://opencollective.com/kingfisher/sponsor/1/avatar.svg"></a>
-<a href="https://opencollective.com/kingfisher/sponsor/2/website" target="_blank"><img src="https://opencollective.com/kingfisher/sponsor/2/avatar.svg"></a>
-<a href="https://opencollective.com/kingfisher/sponsor/3/website" target="_blank"><img src="https://opencollective.com/kingfisher/sponsor/3/avatar.svg"></a>
-<a href="https://opencollective.com/kingfisher/sponsor/4/website" target="_blank"><img src="https://opencollective.com/kingfisher/sponsor/4/avatar.svg"></a>
-<a href="https://opencollective.com/kingfisher/sponsor/5/website" target="_blank"><img src="https://opencollective.com/kingfisher/sponsor/5/avatar.svg"></a>
-<a href="https://opencollective.com/kingfisher/sponsor/6/website" target="_blank"><img src="https://opencollective.com/kingfisher/sponsor/6/avatar.svg"></a>
-<a href="https://opencollective.com/kingfisher/sponsor/7/website" target="_blank"><img src="https://opencollective.com/kingfisher/sponsor/7/avatar.svg"></a>
-<a href="https://opencollective.com/kingfisher/sponsor/8/website" target="_blank"><img src="https://opencollective.com/kingfisher/sponsor/8/avatar.svg"></a>
-<a href="https://opencollective.com/kingfisher/sponsor/9/website" target="_blank"><img src="https://opencollective.com/kingfisher/sponsor/9/avatar.svg"></a>
+## Backers & Sponsors
 
+Open-source projects cannot live long without your help. If you find Kingfisher is useful, please consider supporting this 
+project by becoming a sponsor. Your user icon or company logo shows up [on my blog](https://onevcat.com/tabs/about/) with a link to your home page. 
 
+Become a sponsor through [GitHub Sponsors](https://github.com/sponsors/onevcat) or [Open Collective](https://opencollective.com/kingfisher#sponsor). :heart:
 
 ### License
 
 Kingfisher is released under the MIT license. See LICENSE for details.
-
-

+ 0 - 503
Example/Pods/Kingfisher/Sources/AnimatedImageView.swift

@@ -1,503 +0,0 @@
-//
-//  AnimatableImageView.swift
-//  Kingfisher
-//
-//  Created by bl4ckra1sond3tre on 4/22/16.
-//
-//  The AnimatableImageView, AnimatedFrame and Animator is a modified version of 
-//  some classes from kaishin's Gifu project (https://github.com/kaishin/Gifu)
-//
-//  The MIT License (MIT)
-//
-//  Copyright (c) 2018 Reda Lemeden.
-//
-//  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.
-//
-//  The name and characters used in the demo of this software are property of their
-//  respective owners.
-
-import UIKit
-import ImageIO
-
-/// Protocol of `AnimatedImageView`.
-public protocol AnimatedImageViewDelegate: AnyObject {
-    /**
-     Called after the animatedImageView has finished each animation loop.
-
-     - parameter imageView: The animatedImageView that is being animated.
-     - parameter count: The looped count.
-     */
-    func animatedImageView(_ imageView: AnimatedImageView, didPlayAnimationLoops count: UInt)
-
-    /**
-     Called after the animatedImageView has reached the max repeat count.
-
-     - parameter imageView: The animatedImageView that is being animated.
-     */
-    func animatedImageViewDidFinishAnimating(_ imageView: AnimatedImageView)
-}
-
-extension AnimatedImageViewDelegate {
-    public func animatedImageView(_ imageView: AnimatedImageView, didPlayAnimationLoops count: UInt) {}
-    public func animatedImageViewDidFinishAnimating(_ imageView: AnimatedImageView) {}
-}
-
-/// `AnimatedImageView` is a subclass of `UIImageView` for displaying animated image.
-open class AnimatedImageView: UIImageView {
-    
-    /// Proxy object for prevending a reference cycle between the CADDisplayLink and AnimatedImageView.
-    class TargetProxy {
-        private weak var target: AnimatedImageView?
-        
-        init(target: AnimatedImageView) {
-            self.target = target
-        }
-        
-        @objc func onScreenUpdate() {
-            target?.updateFrame()
-        }
-    }
-
-    /// Enumeration that specifies repeat count of GIF
-    public enum RepeatCount: Equatable {
-        case once
-        case finite(count: UInt)
-        case infinite
-
-        public static func ==(lhs: RepeatCount, rhs: RepeatCount) -> Bool {
-            switch (lhs, rhs) {
-            case let (.finite(l), .finite(r)):
-                return l == r
-            case (.once, .once),
-                 (.infinite, .infinite):
-                return true
-            case (.once, .finite(let count)),
-                 (.finite(let count), .once):
-                return count == 1
-            case (.once, _),
-                 (.infinite, _),
-                 (.finite, _):
-                return false
-            }
-        }
-    }
-    
-    // MARK: - Public property
-    /// Whether automatically play the animation when the view become visible. Default is true.
-    public var autoPlayAnimatedImage = true
-    
-    /// The size of the frame cache.
-    public var framePreloadCount = 10
-    
-    /// Specifies whether the GIF frames should be pre-scaled to save memory. Default is true.
-    public var needsPrescaling = true
-    
-    /// The animation timer's run loop mode. Default is `NSRunLoopCommonModes`. Set this property to `NSDefaultRunLoopMode` will make the animation pause during UIScrollView scrolling.
-    #if swift(>=4.2)
-    public var runLoopMode = RunLoop.Mode.common {
-        willSet {
-            if runLoopMode == newValue {
-                return
-            } else {
-                stopAnimating()
-                displayLink.remove(from: .main, forMode: runLoopMode)
-                displayLink.add(to: .main, forMode: newValue)
-                startAnimating()
-            }
-        }
-    }
-    #else
-    public var runLoopMode = RunLoopMode.commonModes {
-        willSet {
-            if runLoopMode == newValue {
-                return
-            } else {
-                stopAnimating()
-                displayLink.remove(from: .main, forMode: runLoopMode)
-                displayLink.add(to: .main, forMode: newValue)
-                startAnimating()
-            }
-        }
-    }
-    #endif
-
-    /// The repeat count.
-    public var repeatCount = RepeatCount.infinite {
-        didSet {
-            if oldValue != repeatCount {
-                reset()
-                setNeedsDisplay()
-                layer.setNeedsDisplay()
-            }
-        }
-    }
-
-    /// Delegate of this `AnimatedImageView` object. See `AnimatedImageViewDelegate` protocol for more.
-    public weak var delegate: AnimatedImageViewDelegate?
-    
-    // MARK: - Private property
-    /// `Animator` instance that holds the frames of a specific image in memory.
-    private var animator: Animator?
-    
-    /// A flag to avoid invalidating the displayLink on deinit if it was never created, because displayLink is so lazy. :D
-    private var isDisplayLinkInitialized: Bool = false
-    
-    /// A display link that keeps calling the `updateFrame` method on every screen refresh.
-    private lazy var displayLink: CADisplayLink = {
-        self.isDisplayLinkInitialized = true
-        let displayLink = CADisplayLink(target: TargetProxy(target: self), selector: #selector(TargetProxy.onScreenUpdate))
-        displayLink.add(to: .main, forMode: self.runLoopMode)
-        displayLink.isPaused = true
-        return displayLink
-    }()
-    
-    // MARK: - Override
-    override open var image: Image? {
-        didSet {
-            if image != oldValue {
-                reset()
-            }
-            setNeedsDisplay()
-            layer.setNeedsDisplay()
-        }
-    }
-    
-    deinit {
-        if isDisplayLinkInitialized {
-            displayLink.invalidate()
-        }
-    }
-    
-    override open var isAnimating: Bool {
-        if isDisplayLinkInitialized {
-            return !displayLink.isPaused
-        } else {
-            return super.isAnimating
-        }
-    }
-    
-    /// Starts the animation.
-    override open func startAnimating() {
-        if self.isAnimating {
-            return
-        } else {
-            if animator?.isReachMaxRepeatCount ?? false {
-                return
-            }
-
-            displayLink.isPaused = false
-        }
-    }
-    
-    /// Stops the animation.
-    override open func stopAnimating() {
-        super.stopAnimating()
-        if isDisplayLinkInitialized {
-            displayLink.isPaused = true
-        }
-    }
-    
-    override open func display(_ layer: CALayer) {
-        if let currentFrame = animator?.currentFrame {
-            layer.contents = currentFrame.cgImage
-        } else {
-            layer.contents = image?.cgImage
-        }
-    }
-    
-    override open func didMoveToWindow() {
-        super.didMoveToWindow()
-        didMove()
-    }
-    
-    override open func didMoveToSuperview() {
-        super.didMoveToSuperview()
-        didMove()
-    }
-
-    // This is for back compatibility that using regular UIImageView to show animated image.
-    override func shouldPreloadAllAnimation() -> Bool {
-        return false
-    }
-
-    // MARK: - Private method
-    /// Reset the animator.
-    private func reset() {
-        animator = nil
-        if let imageSource = image?.kf.imageSource?.imageRef {
-            animator = Animator(imageSource: imageSource,
-                                contentMode: contentMode,
-                                size: bounds.size,
-                                framePreloadCount: framePreloadCount,
-                                repeatCount: repeatCount)
-            animator?.delegate = self
-            animator?.needsPrescaling = needsPrescaling
-            animator?.prepareFramesAsynchronously()
-        }
-        didMove()
-    }
-    
-    private func didMove() {
-        if autoPlayAnimatedImage && animator != nil {
-            if let _ = superview, let _ = window {
-                startAnimating()
-            } else {
-                stopAnimating()
-            }
-        }
-    }
-    
-    /// Update the current frame with the displayLink duration.
-    private func updateFrame() {
-        let duration: CFTimeInterval
-
-        // CA based display link is opt-out from ProMotion by default.
-        // So the duration and its FPS might not match. 
-        // See [#718](https://github.com/onevcat/Kingfisher/issues/718)
-        if #available(iOS 10.0, tvOS 10.0, *) {
-            // By setting CADisableMinimumFrameDuration to YES in Info.plist may 
-            // cause the preferredFramesPerSecond being 0
-            if displayLink.preferredFramesPerSecond == 0 {
-                duration = displayLink.duration
-            } else {
-                // Some devices (like iPad Pro 10.5) will have a different FPS.
-                duration = 1.0 / Double(displayLink.preferredFramesPerSecond)
-            }
-        } else {
-            duration = displayLink.duration
-        }
-    
-        if animator?.updateCurrentFrame(duration: duration) ?? false {
-            layer.setNeedsDisplay()
-
-            if animator?.isReachMaxRepeatCount ?? false {
-                stopAnimating()
-                delegate?.animatedImageViewDidFinishAnimating(self)
-            }
-        }
-    }
-}
-
-extension AnimatedImageView: AnimatorDelegate {
-    func animator(_ animator: Animator, didPlayAnimationLoops count: UInt) {
-        delegate?.animatedImageView(self, didPlayAnimationLoops: count)
-    }
-}
-
-/// Keeps a reference to an `Image` instance and its duration as a GIF frame.
-struct AnimatedFrame {
-    var image: Image?
-    let duration: TimeInterval
-    
-    static let null: AnimatedFrame = AnimatedFrame(image: .none, duration: 0.0)
-}
-
-protocol AnimatorDelegate: AnyObject {
-    func animator(_ animator: Animator, didPlayAnimationLoops count: UInt)
-}
-
-// MARK: - Animator
-class Animator {
-    // MARK: Private property
-    fileprivate let size: CGSize
-    fileprivate let maxFrameCount: Int
-    fileprivate let imageSource: CGImageSource
-    fileprivate let maxRepeatCount: AnimatedImageView.RepeatCount
-    
-    fileprivate var animatedFrames = [AnimatedFrame]()
-    fileprivate let maxTimeStep: TimeInterval = 1.0
-    fileprivate var frameCount = 0
-    fileprivate var currentFrameIndex = 0
-    fileprivate var currentFrameIndexInBuffer = 0
-    fileprivate var currentPreloadIndex = 0
-    fileprivate var timeSinceLastFrameChange: TimeInterval = 0.0
-    fileprivate var needsPrescaling = true
-    fileprivate var currentRepeatCount: UInt = 0
-    fileprivate weak var delegate: AnimatorDelegate?
-    
-    /// Loop count of animated image.
-    private var loopCount = 0
-    
-    var currentFrame: UIImage? {
-        return frame(at: currentFrameIndexInBuffer)
-    }
-
-    var isReachMaxRepeatCount: Bool {
-        switch maxRepeatCount {
-        case .once:
-            return currentRepeatCount >= 1
-        case .finite(let maxCount):
-            return currentRepeatCount >= maxCount
-        case .infinite:
-            return false
-        }
-    }
-    
-    var contentMode = UIView.ContentMode.scaleToFill
-    
-    private lazy var preloadQueue: DispatchQueue = {
-        return DispatchQueue(label: "com.onevcat.Kingfisher.Animator.preloadQueue")
-    }()
-    
-    /**
-     Init an animator with image source reference.
-     
-     - parameter imageSource: The reference of animated image.
-     - parameter contentMode: Content mode of AnimatedImageView.
-     - parameter size: Size of AnimatedImageView.
-     - parameter framePreloadCount: Frame cache size.
-     
-     - returns: The animator object.
-     */
-    init(imageSource source: CGImageSource,
-         contentMode mode: UIView.ContentMode,
-         size: CGSize,
-         framePreloadCount count: Int,
-         repeatCount: AnimatedImageView.RepeatCount) {
-        self.imageSource = source
-        self.contentMode = mode
-        self.size = size
-        self.maxFrameCount = count
-        self.maxRepeatCount = repeatCount
-    }
-    
-    func frame(at index: Int) -> Image? {
-        return animatedFrames[safe: index]?.image
-    }
-    
-    func prepareFramesAsynchronously() {
-        preloadQueue.async { [weak self] in
-            self?.prepareFrames()
-        }
-    }
-    
-    private func prepareFrames() {
-        frameCount = CGImageSourceGetCount(imageSource)
-        
-        if let properties = CGImageSourceCopyProperties(imageSource, nil),
-            let gifInfo = (properties as NSDictionary)[kCGImagePropertyGIFDictionary as String] as? NSDictionary,
-            let loopCount = gifInfo[kCGImagePropertyGIFLoopCount as String] as? Int
-        {
-            self.loopCount = loopCount
-        }
-        
-        let frameToProcess = min(frameCount, maxFrameCount)
-        animatedFrames.reserveCapacity(frameToProcess)
-        animatedFrames = (0..<frameToProcess).reduce([]) { $0 + pure(prepareFrame(at: $1))}
-        currentPreloadIndex = (frameToProcess + 1) % frameCount - 1
-    }
-    
-    private func prepareFrame(at index: Int) -> AnimatedFrame {
-        
-        guard let imageRef = CGImageSourceCreateImageAtIndex(imageSource, index, nil) else {
-            return AnimatedFrame.null
-        }
-        
-        let defaultGIFFrameDuration = 0.100
-        let frameDuration = imageSource.kf.gifProperties(at: index).map {
-            gifInfo -> Double in
-            
-            let unclampedDelayTime = gifInfo[kCGImagePropertyGIFUnclampedDelayTime as String] as Double?
-            let delayTime = gifInfo[kCGImagePropertyGIFDelayTime as String] as Double?
-            let duration = unclampedDelayTime ?? delayTime ?? 0.0
-            
-            /**
-             http://opensource.apple.com/source/WebCore/WebCore-7600.1.25/platform/graphics/cg/ImageSourceCG.cpp
-             Many annoying ads specify a 0 duration to make an image flash as quickly as
-             possible. We follow Safari and Firefox's behavior and use a duration of 100 ms
-             for any frames that specify a duration of <= 10 ms.
-             See <rdar://problem/7689300> and <http://webkit.org/b/36082> for more information.
-             
-             See also: http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser.
-             */
-            return duration > 0.011 ? duration : defaultGIFFrameDuration
-        } ?? defaultGIFFrameDuration
-        
-        let image = Image(cgImage: imageRef)
-        let scaledImage: Image?
-        
-        if needsPrescaling {
-            scaledImage = image.kf.resize(to: size, for: contentMode)
-        } else {
-            scaledImage = image
-        }
-        
-        return AnimatedFrame(image: scaledImage, duration: frameDuration)
-    }
-    
-    /**
-     Updates the current frame if necessary using the frame timer and the duration of each frame in `animatedFrames`.
-     */
-    func updateCurrentFrame(duration: CFTimeInterval) -> Bool {
-        timeSinceLastFrameChange += min(maxTimeStep, duration)
-        guard let frameDuration = animatedFrames[safe: currentFrameIndexInBuffer]?.duration, frameDuration <= timeSinceLastFrameChange else {
-            return false
-        }
-        
-        timeSinceLastFrameChange -= frameDuration
-        
-        let lastFrameIndex = currentFrameIndexInBuffer
-        currentFrameIndexInBuffer += 1
-        currentFrameIndexInBuffer = currentFrameIndexInBuffer % animatedFrames.count
-        
-        if animatedFrames.count < frameCount {
-            preloadFrameAsynchronously(at: lastFrameIndex)
-        }
-        
-        currentFrameIndex += 1
-        
-        if currentFrameIndex == frameCount {
-            currentFrameIndex = 0
-            currentRepeatCount += 1
-
-            delegate?.animator(self, didPlayAnimationLoops: currentRepeatCount)
-        }
-
-        return true
-    }
-    
-    private func preloadFrameAsynchronously(at index: Int) {
-        preloadQueue.async { [weak self] in
-            self?.preloadFrame(at: index)
-        }
-    }
-    
-    private func preloadFrame(at index: Int) {
-        animatedFrames[index] = prepareFrame(at: currentPreloadIndex)
-        currentPreloadIndex += 1
-        currentPreloadIndex = currentPreloadIndex % frameCount
-    }
-}
-
-extension CGImageSource: KingfisherCompatible { }
-extension Kingfisher where Base: CGImageSource {
-    func gifProperties(at index: Int) -> [String: Double]? {
-        let properties = CGImageSourceCopyPropertiesAtIndex(base, index, nil) as Dictionary?
-        return properties?[kCGImagePropertyGIFDictionary] as? [String: Double]
-    }
-}
-
-extension Array {
-    fileprivate subscript(safe index: Int) -> Element? {
-        return indices ~= index ? self[index] : nil
-    }
-}
-
-private func pure<T>(_ value: T) -> [T] {
-    return [value]
-}

+ 0 - 34
Example/Pods/Kingfisher/Sources/Box.swift

@@ -1,34 +0,0 @@
-//
-//  Box.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 2018/3/17.
-//  Copyright (c) 2018 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.
-
-import Foundation
-
-class Box<T> {
-    let value: T
-    
-    init(_ value: T) {
-        self.value = value
-    }
-}

+ 0 - 87
Example/Pods/Kingfisher/Sources/CacheSerializer.swift

@@ -1,87 +0,0 @@
-//
-//  CacheSerializer.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 2016/09/02.
-//
-//  Copyright (c) 2018 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.
-
-import Foundation
-
-/// An `CacheSerializer` would be used to convert some data to an image object for 
-/// retrieving from disk cache and vice versa for storing to disk cache.
-public protocol CacheSerializer {
-    
-    /// Get the serialized data from a provided image
-    /// and optional original data for caching to disk.
-    ///
-    ///
-    /// - parameter image:    The image needed to be serialized.
-    /// - parameter original: The original data which is just downloaded. 
-    ///                       If the image is retrieved from cache instead of
-    ///                       downloaded, it will be `nil`.
-    ///
-    /// - returns: A data which will be stored to cache, or `nil` when no valid
-    ///            data could be serialized.
-    func data(with image: Image, original: Data?) -> Data?
-    
-    /// Get an image deserialized from provided data.
-    ///
-    /// - parameter data:    The data from which an image should be deserialized.
-    /// - parameter options: Options for deserialization.
-    ///
-    /// - returns: An image deserialized or `nil` when no valid image 
-    ///            could be deserialized.
-    func image(with data: Data, options: KingfisherOptionsInfo?) -> Image?
-}
-
-
-/// `DefaultCacheSerializer` is a basic `CacheSerializer` used in default cache of
-/// Kingfisher. It could serialize and deserialize PNG, JEPG and GIF images. For 
-/// image other than these formats, a normalized `pngRepresentation` will be used.
-public struct DefaultCacheSerializer: CacheSerializer {
-    
-    public static let `default` = DefaultCacheSerializer()
-    private init() {}
-    
-    public func data(with image: Image, original: Data?) -> Data? {
-        let imageFormat = original?.kf.imageFormat ?? .unknown
-
-        let data: Data?
-        switch imageFormat {
-        case .PNG: data = image.kf.pngRepresentation()
-        case .JPEG: data = image.kf.jpegRepresentation(compressionQuality: 1.0)
-        case .GIF: data = image.kf.gifRepresentation()
-        case .unknown: data = original ?? image.kf.normalized.kf.pngRepresentation()
-        }
-
-        return data
-    }
-    
-    public func image(with data: Data, options: KingfisherOptionsInfo?) -> Image? {
-        let options = options ?? KingfisherEmptyOptionsInfo
-        return Kingfisher<Image>.image(
-            data: data,
-            scale: options.scaleFactor,
-            preloadAllAnimationData: options.preloadAllAnimationData,
-            onlyFirstFrame: options.onlyLoadFirstFrame)
-    }
-}

+ 0 - 144
Example/Pods/Kingfisher/Sources/Filter.swift

@@ -1,144 +0,0 @@
-//
-//  Filter.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 2016/08/31.
-//
-//  Copyright (c) 2018 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.
-
-
-
-import CoreImage
-import Accelerate
-
-// Reuse the same CI Context for all CI drawing.
-private let ciContext = CIContext(options: nil)
-
-/// Transformer method which will be used in to provide a `Filter`.
-public typealias Transformer = (CIImage) -> CIImage?
-
-/// Supply a filter to create an `ImageProcessor`.
-public protocol CIImageProcessor: ImageProcessor {
-    var filter: Filter { get }
-}
-
-extension CIImageProcessor {
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        switch item {
-        case .image(let image):
-            return image.kf.apply(filter)
-        case .data(_):
-            return (DefaultImageProcessor.default >> self).process(item: item, options: options)
-        }
-    }
-}
-
-/// Wrapper for a `Transformer` of CIImage filters.
-public struct Filter {
-    
-    let transform: Transformer
-
-    public init(transform: @escaping Transformer) {
-        self.transform = transform
-    }
-    
-    /// Tint filter which will apply a tint color to images.
-    public static var tint: (Color) -> Filter = {
-        color in
-        Filter(transform: { input in
-            let colorFilter = CIFilter(name: "CIConstantColorGenerator")!
-            colorFilter.setValue(CIColor(color: color), forKey: kCIInputColorKey)
-            
-            let colorImage = colorFilter.outputImage
-            let filter = CIFilter(name: "CISourceOverCompositing")!
-            filter.setValue(colorImage, forKey: kCIInputImageKey)
-            filter.setValue(input, forKey: kCIInputBackgroundImageKey)
-            #if swift(>=4.0)
-            return filter.outputImage?.cropped(to: input.extent)
-            #else
-            return filter.outputImage?.cropping(to: input.extent)
-            #endif
-        })
-    }
-    
-    public typealias ColorElement = (CGFloat, CGFloat, CGFloat, CGFloat)
-    
-    /// Color control filter which will apply color control change to images.
-    public static var colorControl: (ColorElement) -> Filter = { arg -> Filter in
-        let (brightness, contrast, saturation, inputEV) = arg
-        return Filter(transform: { input in
-            let paramsColor = [kCIInputBrightnessKey: brightness,
-                               kCIInputContrastKey: contrast,
-                               kCIInputSaturationKey: saturation]
-            
-            let paramsExposure = [kCIInputEVKey: inputEV]
-            #if swift(>=4.0)
-            let blackAndWhite = input.applyingFilter("CIColorControls", parameters: paramsColor)
-            return blackAndWhite.applyingFilter("CIExposureAdjust", parameters: paramsExposure)
-            #else
-            let blackAndWhite = input.applyingFilter("CIColorControls", withInputParameters: paramsColor)
-            return blackAndWhite.applyingFilter("CIExposureAdjust", withInputParameters: paramsExposure)
-            #endif
-        })
-    }
-}
-
-// MARK: - Deprecated
-extension Filter {
-    @available(*, deprecated, message: "Use init(transform:) instead.", renamed: "init(transform:)")
-    public init(tranform: @escaping Transformer) {
-        self.transform = tranform
-    }
-}
-
-extension Kingfisher where Base: Image {
-    /// Apply a `Filter` containing `CIImage` transformer to `self`.
-    ///
-    /// - parameter filter: The filter used to transform `self`.
-    ///
-    /// - returns: A transformed image by input `Filter`.
-    ///
-    /// - Note: Only CG-based images are supported. If any error happens during transforming, `self` will be returned.
-    public func apply(_ filter: Filter) -> Image {
-        
-        guard let cgImage = cgImage else {
-            assertionFailure("[Kingfisher] Tint image only works for CG-based image.")
-            return base
-        }
-        
-        let inputImage = CIImage(cgImage: cgImage)
-        guard let outputImage = filter.transform(inputImage) else {
-            return base
-        }
-        
-        guard let result = ciContext.createCGImage(outputImage, from: outputImage.extent) else {
-            assertionFailure("[Kingfisher] Can not make an tint image within context.")
-            return base
-        }
-        
-        #if os(macOS)
-            return fixedForRetinaPixel(cgImage: result, to: size)
-        #else
-            return Image(cgImage: result, scale: base.scale, orientation: base.imageOrientation)
-        #endif
-    }
-
-}

+ 0 - 96
Example/Pods/Kingfisher/Sources/FormatIndicatedCacheSerializer.swift

@@ -1,96 +0,0 @@
-//
-//  RequestModifier.swift
-//  Kingfisher
-//
-//  Created by Junyu Kuang on 5/28/17.
-//
-//  Copyright (c) 2018 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.
-
-import Foundation
-
-/// `FormatIndicatedCacheSerializer` let you indicate an image format for serialized caches.
-///
-/// It could serialize and deserialize PNG, JEPG and GIF images. For
-/// image other than these formats, a normalized `pngRepresentation` will be used.
-///
-/// Example:
-/// ````
-/// private let profileImageSize = CGSize(width: 44, height: 44)
-///
-/// private let imageProcessor = RoundCornerImageProcessor(
-///     cornerRadius: profileImageSize.width / 2, targetSize: profileImageSize)
-///
-/// private let optionsInfo: KingfisherOptionsInfo = [
-///     .cacheSerializer(FormatIndicatedCacheSerializer.png), 
-///     .backgroundDecode, .processor(imageProcessor), .scaleFactor(UIScreen.main.scale)]
-///
-/// extension UIImageView {
-///    func setProfileImage(with url: URL) {
-///        // Image will always cached as PNG format to preserve alpha channel for round rect.
-///        _ = kf.setImage(with: url, options: optionsInfo)
-///    }
-///}
-/// ````
-public struct FormatIndicatedCacheSerializer: CacheSerializer {
-    
-    public static let png = FormatIndicatedCacheSerializer(imageFormat: .PNG)
-    public static let jpeg = FormatIndicatedCacheSerializer(imageFormat: .JPEG)
-    public static let gif = FormatIndicatedCacheSerializer(imageFormat: .GIF)
-    
-    /// The indicated image format.
-    private let imageFormat: ImageFormat
-    
-    public func data(with image: Image, original: Data?) -> Data? {
-        
-        func imageData(withFormat imageFormat: ImageFormat) -> Data? {
-            switch imageFormat {
-            case .PNG: return image.kf.pngRepresentation()
-            case .JPEG: return image.kf.jpegRepresentation(compressionQuality: 1.0)
-            case .GIF: return image.kf.gifRepresentation()
-            case .unknown: return nil
-            }
-        }
-        
-        // generate data with indicated image format
-        if let data = imageData(withFormat: imageFormat) {
-            return data
-        }
-        
-        let originalFormat = original?.kf.imageFormat ?? .unknown
-        
-        // generate data with original image's format
-        if originalFormat != imageFormat, let data = imageData(withFormat: originalFormat) {
-            return data
-        }
-        
-        return original ?? image.kf.normalized.kf.pngRepresentation()
-    }
-    
-    /// Same implementation as `DefaultCacheSerializer`.
-    public func image(with data: Data, options: KingfisherOptionsInfo?) -> Image? {
-        let options = options ?? KingfisherEmptyOptionsInfo
-        return Kingfisher<Image>.image(
-            data: data,
-            scale: options.scaleFactor,
-            preloadAllAnimationData: options.preloadAllAnimationData,
-            onlyFirstFrame: options.onlyLoadFirstFrame)
-    }
-}

+ 0 - 1045
Example/Pods/Kingfisher/Sources/Image.swift

@@ -1,1045 +0,0 @@
-//
-//  Image.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 16/1/6.
-//
-//  Copyright (c) 2018 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.
-
-
-#if os(macOS)
-import AppKit
-private var imagesKey: Void?
-private var durationKey: Void?
-#else
-import UIKit
-import MobileCoreServices
-private var imageSourceKey: Void?
-#endif
-private var animatedImageDataKey: Void?
-
-import ImageIO
-import CoreGraphics
-
-#if !os(watchOS)
-import Accelerate
-import CoreImage
-#endif
-
-// MARK: - Image Properties
-extension Kingfisher where Base: Image {
-    fileprivate(set) var animatedImageData: Data? {
-        get {
-            return objc_getAssociatedObject(base, &animatedImageDataKey) as? Data
-        }
-        set {
-            objc_setAssociatedObject(base, &animatedImageDataKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-        }
-    }
-    
-    #if os(macOS)
-    var cgImage: CGImage? {
-        return base.cgImage(forProposedRect: nil, context: nil, hints: nil)
-    }
-    
-    var scale: CGFloat {
-        return 1.0
-    }
-    
-    fileprivate(set) var images: [Image]? {
-        get {
-            return objc_getAssociatedObject(base, &imagesKey) as? [Image]
-        }
-        set {
-            objc_setAssociatedObject(base, &imagesKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-        }
-    }
-    
-    fileprivate(set) var duration: TimeInterval {
-        get {
-            return objc_getAssociatedObject(base, &durationKey) as? TimeInterval ?? 0.0
-        }
-        set {
-            objc_setAssociatedObject(base, &durationKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-        }
-    }
-    
-    var size: CGSize {
-        return base.representations.reduce(CGSize.zero, { size, rep in
-            return CGSize(width: max(size.width, CGFloat(rep.pixelsWide)), height: max(size.height, CGFloat(rep.pixelsHigh)))
-        })
-    }
-    
-    #else
-    var cgImage: CGImage? {
-        return base.cgImage
-    }
-    
-    var scale: CGFloat {
-        return base.scale
-    }
-    
-    var images: [Image]? {
-        return base.images
-    }
-    
-    var duration: TimeInterval {
-        return base.duration
-    }
-    
-    fileprivate(set) var imageSource: ImageSource? {
-        get {
-            return objc_getAssociatedObject(base, &imageSourceKey) as? ImageSource
-        }
-        set {
-            objc_setAssociatedObject(base, &imageSourceKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-        }
-    }
-    
-    var size: CGSize {
-        return base.size
-    }
-    #endif
-}
-
-// MARK: - Image Conversion
-extension Kingfisher where Base: Image {
-    #if os(macOS)
-    static func image(cgImage: CGImage, scale: CGFloat, refImage: Image?) -> Image {
-        return Image(cgImage: cgImage, size: CGSize.zero)
-    }
-    
-    /**
-     Normalize the image. This method does nothing in OS X.
-     
-     - returns: The image itself.
-     */
-    public var normalized: Image {
-        return base
-    }
-    
-    static func animated(with images: [Image], forDuration forDurationduration: TimeInterval) -> Image? {
-        return nil
-    }
-    #else
-    static func image(cgImage: CGImage, scale: CGFloat, refImage: Image?) -> Image {
-        if let refImage = refImage {
-            return Image(cgImage: cgImage, scale: scale, orientation: refImage.imageOrientation)
-        } else {
-            return Image(cgImage: cgImage, scale: scale, orientation: .up)
-        }
-    }
-    
-    /**
-     Normalize the image. This method will try to redraw an image with orientation and scale considered.
-     
-     - returns: The normalized image with orientation set to up and correct scale.
-     */
-    public var normalized: Image {
-        // prevent animated image (GIF) lose it's images
-        guard images == nil else { return base }
-        // No need to do anything if already up
-        guard base.imageOrientation != .up else { return base }
-    
-        return draw(cgImage: nil, to: size) {
-            base.draw(in: CGRect(origin: CGPoint.zero, size: size))
-        }
-    }
-    
-    static func animated(with images: [Image], forDuration duration: TimeInterval) -> Image? {
-        return .animatedImage(with: images, duration: duration)
-    }
-    #endif
-}
-
-// MARK: - Image Representation
-extension Kingfisher where Base: Image {
-    // MARK: - PNG
-    public func pngRepresentation() -> Data? {
-        #if os(macOS)
-            guard let cgimage = cgImage else {
-                return nil
-            }
-            let rep = NSBitmapImageRep(cgImage: cgimage)
-            return rep.representation(using: .png, properties: [:])
-        #else
-            #if swift(>=4.2)
-            return base.pngData()
-            #else
-            return UIImagePNGRepresentation(base)
-            #endif
-        #endif
-    }
-    
-    // MARK: - JPEG
-    public func jpegRepresentation(compressionQuality: CGFloat) -> Data? {
-        #if os(macOS)
-            guard let cgImage = cgImage else {
-                return nil
-            }
-            let rep = NSBitmapImageRep(cgImage: cgImage)
-            return rep.representation(using:.jpeg, properties: [.compressionFactor: compressionQuality])
-        #else
-            #if swift(>=4.2)
-            return base.jpegData(compressionQuality: compressionQuality)
-            #else
-            return UIImageJPEGRepresentation(base, compressionQuality)
-            #endif
-        #endif
-    }
-    
-    // MARK: - GIF
-    public func gifRepresentation() -> Data? {
-        return animatedImageData
-    }
-}
-
-// MARK: - Create images from data
-extension Kingfisher where Base: Image {
-    public static func animated(with data: Data, scale: CGFloat = 1.0, duration: TimeInterval = 0.0, preloadAll: Bool, onlyFirstFrame: Bool = false) -> Image? {
-        
-        func decode(from imageSource: CGImageSource, for options: NSDictionary) -> ([Image], TimeInterval)? {
-            
-            //Calculates frame duration for a gif frame out of the kCGImagePropertyGIFDictionary dictionary
-            func frameDuration(from gifInfo: NSDictionary?) -> Double {
-                let gifDefaultFrameDuration = 0.100
-                
-                guard let gifInfo = gifInfo else {
-                    return gifDefaultFrameDuration
-                }
-                
-                let unclampedDelayTime = gifInfo[kCGImagePropertyGIFUnclampedDelayTime as String] as? NSNumber
-                let delayTime = gifInfo[kCGImagePropertyGIFDelayTime as String] as? NSNumber
-                let duration = unclampedDelayTime ?? delayTime
-                
-                guard let frameDuration = duration else { return gifDefaultFrameDuration }
-                
-                return frameDuration.doubleValue > 0.011 ? frameDuration.doubleValue : gifDefaultFrameDuration
-            }
-            
-            let frameCount = CGImageSourceGetCount(imageSource)
-            var images = [Image]()
-            var gifDuration = 0.0
-            for i in 0 ..< frameCount {
-                
-                guard let imageRef = CGImageSourceCreateImageAtIndex(imageSource, i, options) else {
-                    return nil
-                }
-
-                if frameCount == 1 {
-                    // Single frame
-                    gifDuration = Double.infinity
-                } else {
-                    
-                    // Animated GIF
-                    guard let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, i, nil) else {
-                        return nil
-                    }
-
-                    let gifInfo = (properties as NSDictionary)[kCGImagePropertyGIFDictionary as String] as? NSDictionary
-                    gifDuration += frameDuration(from: gifInfo)
-                }
-                
-                images.append(Kingfisher<Image>.image(cgImage: imageRef, scale: scale, refImage: nil))
-                
-                if onlyFirstFrame { break }
-            }
-            
-            return (images, gifDuration)
-        }
-        
-        // Start of kf.animatedImageWithGIFData
-        let options: NSDictionary = [kCGImageSourceShouldCache as String: true, kCGImageSourceTypeIdentifierHint as String: kUTTypeGIF]
-        guard let imageSource = CGImageSourceCreateWithData(data as CFData, options) else {
-            return nil
-        }
-        
-        #if os(macOS)
-            guard let (images, gifDuration) = decode(from: imageSource, for: options) else {
-                return nil
-            }
-            let image: Image?
-            if onlyFirstFrame {
-                image = images.first
-            } else {
-                image = Image(data: data)
-                image?.kf.images = images
-                image?.kf.duration = gifDuration
-            }
-            image?.kf.animatedImageData = data
-            return image
-        #else
-            
-            let image: Image?
-            if preloadAll || onlyFirstFrame {
-                guard let (images, gifDuration) = decode(from: imageSource, for: options) else { return nil }
-                image = onlyFirstFrame ? images.first : Kingfisher<Image>.animated(with: images, forDuration: duration <= 0.0 ? gifDuration : duration)
-            } else {
-                image = Image(data: data, scale: scale)
-                image?.kf.imageSource = ImageSource(ref: imageSource)
-            }
-            image?.kf.animatedImageData = data
-            return image
-        #endif
-    }
-
-    public static func image(data: Data, scale: CGFloat, preloadAllAnimationData: Bool, onlyFirstFrame: Bool) -> Image? {
-        var image: Image?
-
-        #if os(macOS)
-            switch data.kf.imageFormat {
-            case .JPEG:
-                image = Image(data: data)
-            case .PNG:
-                image = Image(data: data)
-            case .GIF:
-                image = Kingfisher<Image>.animated(
-                    with: data,
-                    scale: scale,
-                    duration: 0.0,
-                    preloadAll: preloadAllAnimationData,
-                    onlyFirstFrame: onlyFirstFrame)
-            case .unknown:
-                image = Image(data: data)
-            }
-        #else
-            switch data.kf.imageFormat {
-            case .JPEG:
-                image = Image(data: data, scale: scale)
-            case .PNG:
-                image = Image(data: data, scale: scale)
-            case .GIF:
-                image = Kingfisher<Image>.animated(
-                    with: data,
-                    scale: scale,
-                    duration: 0.0,
-                    preloadAll: preloadAllAnimationData,
-                    onlyFirstFrame: onlyFirstFrame)
-            case .unknown:
-                image = Image(data: data, scale: scale)
-            }
-        #endif
-
-        return image
-    }
-}
-
-// MARK: - Image Transforming
-extension Kingfisher where Base: Image {
-    // MARK: - Blend Mode
-    /// Create image based on `self` and apply blend mode.
-    ///
-    /// - parameter blendMode:       The blend mode of creating image.
-    /// - parameter alpha:           The alpha should be used for image.
-    /// - parameter backgroundColor: The background color for the output image.
-    ///
-    /// - returns: An image with blend mode applied.
-    ///
-    /// - Note: This method only works for CG-based image.
-    #if !os(macOS)
-    public func image(withBlendMode blendMode: CGBlendMode,
-                      alpha: CGFloat = 1.0,
-                      backgroundColor: Color? = nil) -> Image
-    {
-        guard let cgImage = cgImage else {
-            assertionFailure("[Kingfisher] Blend mode image only works for CG-based image.")
-            return base
-        }
-
-        let rect = CGRect(origin: .zero, size: size)
-        return draw(cgImage: cgImage, to: rect.size) {
-            if let backgroundColor = backgroundColor {
-                backgroundColor.setFill()
-                UIRectFill(rect)
-            }
-
-            base.draw(in: rect, blendMode: blendMode, alpha: alpha)
-        }
-    }
-    #endif
-
-    // MARK: - Compositing Operation
-    /// Create image based on `self` and apply compositing operation.
-    ///
-    /// - parameter compositingOperation: The compositing operation of creating image.
-    /// - parameter alpha:                The alpha should be used for image.
-    /// - parameter backgroundColor:      The background color for the output image.
-    ///
-    /// - returns: An image with compositing operation applied.
-    ///
-    /// - Note: This method only works for CG-based image.
-    #if os(macOS)
-    public func image(withCompositingOperation compositingOperation: NSCompositingOperation,
-                      alpha: CGFloat = 1.0,
-                      backgroundColor: Color? = nil) -> Image
-    {
-        guard let cgImage = cgImage else {
-            assertionFailure("[Kingfisher] Compositing Operation image only works for CG-based image.")
-            return base
-        }
-
-        let rect = CGRect(origin: .zero, size: size)
-        return draw(cgImage: cgImage, to: rect.size) {
-            if let backgroundColor = backgroundColor {
-                backgroundColor.setFill()
-                rect.fill()
-            }
-
-            base.draw(in: rect, from: NSRect.zero, operation: compositingOperation, fraction: alpha)
-        }
-    }
-    #endif
-
-    // MARK: - Round Corner
-    /// Create a round corner image based on `self`.
-    ///
-    /// - parameter radius:          The round corner radius of creating image.
-    /// - parameter size:            The target size of creating image.
-    /// - parameter corners:         The target corners which will be applied rounding.
-    /// - parameter backgroundColor: The background color for the output image
-    ///
-    /// - returns: An image with round corner of `self`.
-    ///
-    /// - Note: This method only works for CG-based image.
-    public func image(withRoundRadius radius: CGFloat,
-                      fit size: CGSize,
-                      roundingCorners corners: RectCorner = .all,
-                      backgroundColor: Color? = nil) -> Image
-    {   
-        guard let cgImage = cgImage else {
-            assertionFailure("[Kingfisher] Round corner image only works for CG-based image.")
-            return base
-        }
-        
-        let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: size)
-        return draw(cgImage: cgImage, to: size) {
-            #if os(macOS)
-                if let backgroundColor = backgroundColor {
-                    let rectPath = NSBezierPath(rect: rect)
-                    backgroundColor.setFill()
-                    rectPath.fill()
-                }
-
-                let path = NSBezierPath(roundedRect: rect, byRoundingCorners: corners, radius: radius)
-                #if swift(>=4.2)
-                path.windingRule = .evenOdd
-                #else
-                path.windingRule = .evenOddWindingRule
-                #endif
-                path.addClip()
-                base.draw(in: rect)
-            #else
-                guard let context = UIGraphicsGetCurrentContext() else {
-                    assertionFailure("[Kingfisher] Failed to create CG context for image.")
-                    return
-                }
-
-                if let backgroundColor = backgroundColor {
-                    let rectPath = UIBezierPath(rect: rect)
-                    backgroundColor.setFill()
-                    rectPath.fill()
-                }
-
-                let path = UIBezierPath(roundedRect: rect,
-                                        byRoundingCorners: corners.uiRectCorner,
-                                        cornerRadii: CGSize(width: radius, height: radius)).cgPath
-                context.addPath(path)
-                context.clip()
-                base.draw(in: rect)
-            #endif
-        }
-    }
-    
-    #if os(iOS) || os(tvOS)
-    func resize(to size: CGSize, for contentMode: UIView.ContentMode) -> Image {
-        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
-    /// Resize `self` to an image of new size.
-    ///
-    /// - parameter size: The target size.
-    ///
-    /// - returns: An image with new size.
-    ///
-    /// - Note: This method only works for CG-based image.
-    public func resize(to size: CGSize) -> Image {
-        
-        guard let cgImage = cgImage else {
-            assertionFailure("[Kingfisher] Resize only works for CG-based image.")
-            return base
-        }
-        
-        let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: size)
-        return draw(cgImage: cgImage, to: size) {
-            #if os(macOS)
-                base.draw(in: rect, from: NSRect.zero, operation: .copy, fraction: 1.0)
-            #else
-                base.draw(in: rect)
-            #endif
-        }
-    }
-    
-    /// Resize `self` to an image of new size, respecting the content mode.
-    ///
-    /// - Parameters:
-    ///   - size: The target size.
-    ///   - contentMode: Content mode of output image should be.
-    /// - Returns: An image with new size.
-    public func resize(to size: CGSize, for contentMode: ContentMode) -> Image {
-        switch contentMode {
-        case .aspectFit:
-            let newSize = self.size.kf.constrained(size)
-            return resize(to: newSize)
-        case .aspectFill:
-            let newSize = self.size.kf.filling(size)
-            return resize(to: newSize)
-        default:
-            return resize(to: size)
-        }
-    }
-    
-    public func crop(to size: CGSize, anchorOn anchor: CGPoint) -> Image {
-        guard let cgImage = cgImage else {
-            assertionFailure("[Kingfisher] Crop only works for CG-based image.")
-            return base
-        }
-        
-        let rect = self.size.kf.constrainedRect(for: size, anchor: anchor)
-        guard let image = cgImage.cropping(to: rect.scaled(scale)) else {
-            assertionFailure("[Kingfisher] Cropping image failed.")
-            return base
-        }
-        
-        return Kingfisher.image(cgImage: image, scale: scale, refImage: base)
-    }
-    
-    // MARK: - Blur
-    
-    /// Create an image with blur effect based on `self`.
-    ///
-    /// - parameter radius: The blur radius should be used when creating blur effect.
-    ///
-    /// - returns: An image with blur effect applied.
-    ///
-    /// - Note: This method only works for CG-based image.
-    public func blurred(withRadius radius: CGFloat) -> Image {
-        #if os(watchOS)
-            return base
-        #else
-            guard let cgImage = cgImage else {
-                assertionFailure("[Kingfisher] Blur only works for CG-based image.")
-                return base
-            }
-            
-            // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
-            // let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)
-            // if d is odd, use three box-blurs of size 'd', centered on the output pixel.
-            let s = Float(max(radius, 2.0))
-            // We will do blur on a resized image (*0.5), so the blur radius could be half as well.
-            
-            // Fix the slow compiling time for Swift 3. 
-            // See https://github.com/onevcat/Kingfisher/issues/611
-            let pi2 = 2 * Float.pi
-            let sqrtPi2 = sqrt(pi2)
-            var targetRadius = floor(s * 3.0 * sqrtPi2 / 4.0 + 0.5)
-            
-            if targetRadius.isEven {
-                targetRadius += 1
-            }
-            
-            let iterations: Int
-            if radius < 0.5 {
-                iterations = 1
-            } else if radius < 1.5 {
-                iterations = 2
-            } else {
-                iterations = 3
-            }
-            
-            let w = Int(size.width)
-            let h = Int(size.height)
-            let rowBytes = Int(CGFloat(cgImage.bytesPerRow))
-            
-            func createEffectBuffer(_ context: CGContext) -> vImage_Buffer {
-                let data = context.data
-                let width = vImagePixelCount(context.width)
-                let height = vImagePixelCount(context.height)
-                let rowBytes = context.bytesPerRow
-                
-                return vImage_Buffer(data: data, height: height, width: width, rowBytes: rowBytes)
-            }
-
-            guard let context = beginContext(size: size, scale: scale) else {
-                assertionFailure("[Kingfisher] Failed to create CG context for blurring image.")
-                return base
-            }
-            defer { endContext() }
-
-            context.draw(cgImage, in: CGRect(x: 0, y: 0, width: w, height: h))
-            
-            var inBuffer = createEffectBuffer(context)
-            
-            guard let outContext = beginContext(size: size, scale: scale) else {
-                assertionFailure("[Kingfisher] Failed to create CG context for blurring image.")
-                return base
-            }
-            defer { endContext() }
-            var outBuffer = createEffectBuffer(outContext)
-            
-            for _ in 0 ..< iterations {
-                vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, nil, 0, 0, UInt32(targetRadius), UInt32(targetRadius), nil, vImage_Flags(kvImageEdgeExtend))
-                (inBuffer, outBuffer) = (outBuffer, inBuffer)
-            }
-            
-            #if os(macOS)
-                let result = outContext.makeImage().flatMap { fixedForRetinaPixel(cgImage: $0, to: size) }
-            #else
-                let result = outContext.makeImage().flatMap { Image(cgImage: $0, scale: base.scale, orientation: base.imageOrientation) }
-            #endif
-            guard let blurredImage = result else {
-                assertionFailure("[Kingfisher] Can not make an blurred image within this context.")
-                return base
-            }
-            
-            return blurredImage
-        #endif
-    }
-    
-    // MARK: - Overlay
-    
-    /// Create an image from `self` with a color overlay layer.
-    ///
-    /// - parameter color:    The color should be use to overlay.
-    /// - parameter fraction: Fraction of input color. From 0.0 to 1.0. 0.0 means solid color, 1.0 means transparent overlay.
-    ///
-    /// - returns: An image with a color overlay applied.
-    ///
-    /// - Note: This method only works for CG-based image.
-    public func overlaying(with color: Color, fraction: CGFloat) -> Image {
-        
-        guard let cgImage = cgImage else {
-            assertionFailure("[Kingfisher] Overlaying only works for CG-based image.")
-            return base
-        }
-        
-        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
-        return draw(cgImage: cgImage, to: rect.size) {
-            #if os(macOS)
-                base.draw(in: rect)
-                if fraction > 0 {
-                    color.withAlphaComponent(1 - fraction).set()
-                    rect.fill(using: .sourceAtop)
-                }
-            #else
-                color.set()
-                UIRectFill(rect)
-                base.draw(in: rect, blendMode: .destinationIn, alpha: 1.0)
-                
-                if fraction > 0 {
-                    base.draw(in: rect, blendMode: .sourceAtop, alpha: fraction)
-                }
-            #endif
-        }
-    }
-    
-    // MARK: - Tint
-    
-    /// Create an image from `self` with a color tint.
-    ///
-    /// - parameter color: The color should be used to tint `self`
-    ///
-    /// - returns: An image with a color tint applied.
-    public func tinted(with color: Color) -> Image {
-        #if os(watchOS)
-            return base
-        #else
-            return apply(.tint(color))
-        #endif
-    }
-    
-    // MARK: - Color Control
-    
-    /// Create an image from `self` with color control.
-    ///
-    /// - parameter brightness: Brightness changing to image.
-    /// - parameter contrast:   Contrast changing to image.
-    /// - parameter saturation: Saturation changing to image.
-    /// - parameter inputEV:    InputEV changing to image.
-    ///
-    /// - returns: An image with color control applied.
-    public func adjusted(brightness: CGFloat, contrast: CGFloat, saturation: CGFloat, inputEV: CGFloat) -> Image {
-        #if os(watchOS)
-            return base
-        #else
-            return apply(.colorControl((brightness, contrast, saturation, inputEV)))
-        #endif
-    }
-
-    /// Return an image with given scale.
-    ///
-    /// - Parameter scale: Target scale factor the new image should have.
-    /// - Returns: The image with target scale. If the base image is already in the scale, `base` will be returned.
-    public func scaled(to scale: CGFloat) -> Image {
-        guard scale != self.scale else {
-            return base
-        }
-        guard let cgImage = cgImage else {
-            assertionFailure("[Kingfisher] Scaling only works for CG-based image.")
-            return base
-        }
-        return Kingfisher.image(cgImage: cgImage, scale: scale, refImage: base)
-    }
-}
-
-// MARK: - Decode
-extension Kingfisher where Base: Image {
-    public var decoded: Image {
-        return decoded(scale: scale)
-    }
-    
-    public func decoded(scale: CGFloat) -> Image {
-        // prevent animated image (GIF) lose it's images
-        #if os(iOS)
-            if imageSource != nil { return base }
-        #else
-            if images != nil { return base }
-        #endif
-        
-        guard let imageRef = self.cgImage else {
-            assertionFailure("[Kingfisher] Decoding only works for CG-based image.")
-            return base
-        }
-        
-        // Draw CGImage in a plain context with scale of 1.0.
-        guard let context = beginContext(size: CGSize(width: imageRef.width, height: imageRef.height), scale: 1.0) else {
-            assertionFailure("[Kingfisher] Decoding fails to create a valid context.")
-            return base
-        }
-        
-        defer { endContext() }
-        
-        let rect = CGRect(x: 0, y: 0, width: CGFloat(imageRef.width), height: CGFloat(imageRef.height))
-        context.draw(imageRef, in: rect)
-        let decompressedImageRef = context.makeImage()
-        return Kingfisher<Image>.image(cgImage: decompressedImageRef!, scale: scale, refImage: base)
-    }
-}
-
-/// Reference the source image reference
-final class ImageSource {
-    var imageRef: CGImageSource?
-    init(ref: CGImageSource) {
-        self.imageRef = ref
-    }
-}
-
-// MARK: - Image format
-private struct ImageHeaderData {
-    static var PNG: [UInt8] = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]
-    static var JPEG_SOI: [UInt8] = [0xFF, 0xD8]
-    static var JPEG_IF: [UInt8] = [0xFF]
-    static var GIF: [UInt8] = [0x47, 0x49, 0x46]
-}
-
-public enum ImageFormat {
-    case unknown, PNG, JPEG, GIF
-}
-
-
-// MARK: - Misc Helpers
-public struct DataProxy {
-    fileprivate let base: Data
-    init(proxy: Data) {
-        base = proxy
-    }
-}
-
-extension Data: KingfisherCompatible {
-    public typealias CompatibleType = DataProxy
-    public var kf: DataProxy {
-        return DataProxy(proxy: self)
-    }
-}
-
-extension DataProxy {
-    public var imageFormat: ImageFormat {
-        var buffer = [UInt8](repeating: 0, count: 8)
-        (base as NSData).getBytes(&buffer, length: 8)
-        if buffer == ImageHeaderData.PNG {
-            return .PNG
-        } else if buffer[0] == ImageHeaderData.JPEG_SOI[0] &&
-            buffer[1] == ImageHeaderData.JPEG_SOI[1] &&
-            buffer[2] == ImageHeaderData.JPEG_IF[0]
-        {
-            return .JPEG
-        } else if buffer[0] == ImageHeaderData.GIF[0] &&
-            buffer[1] == ImageHeaderData.GIF[1] &&
-            buffer[2] == ImageHeaderData.GIF[2]
-        {
-            return .GIF
-        }
-
-        return .unknown
-    }
-}
-
-public struct CGSizeProxy {
-    fileprivate let base: CGSize
-    init(proxy: CGSize) {
-        base = proxy
-    }
-}
-
-extension CGSize: KingfisherCompatible {
-    public typealias CompatibleType = CGSizeProxy
-    public var kf: CGSizeProxy {
-        return CGSizeProxy(proxy: self)
-    }
-}
-
-extension CGSizeProxy {
-    
-    public func resize(to size: CGSize, for contentMode: ContentMode) -> CGSize {
-        switch contentMode {
-        case .aspectFit:
-            return constrained(size)
-        case .aspectFill:
-            return filling(size)
-        default:
-            return self.base
-        }
-    }
-    
-    public func constrained(_ size: CGSize) -> CGSize {
-        let aspectWidth = round(aspectRatio * size.height)
-        let aspectHeight = round(size.width / aspectRatio)
-
-        return aspectWidth > size.width ? CGSize(width: size.width, height: aspectHeight) : CGSize(width: aspectWidth, height: size.height)
-    }
-
-    public func filling(_ size: CGSize) -> CGSize {
-        let aspectWidth = round(aspectRatio * size.height)
-        let aspectHeight = round(size.width / aspectRatio)
-
-        return aspectWidth < size.width ? CGSize(width: size.width, height: aspectHeight) : CGSize(width: aspectWidth, height: size.height)
-    }
-
-    private var aspectRatio: CGFloat {
-        return base.height == 0.0 ? 1.0 : base.width / base.height
-    }
-    
-    
-    public func constrainedRect(for size: CGSize, anchor: CGPoint) -> CGRect {
-        
-        let unifiedAnchor = CGPoint(x: anchor.x.clamped(to: 0.0...1.0),
-                                    y: anchor.y.clamped(to: 0.0...1.0))
-        
-        let x = unifiedAnchor.x * base.width - unifiedAnchor.x * size.width
-        let y = unifiedAnchor.y * base.height - unifiedAnchor.y * size.height
-        let r = CGRect(x: x, y: y, width: size.width, height: size.height)
-        
-        let ori = CGRect(origin: CGPoint.zero, size: base)
-        return ori.intersection(r)
-    }
-}
-
-extension CGRect {
-    func scaled(_ scale: CGFloat) -> CGRect {
-        return CGRect(x: origin.x * scale, y: origin.y * scale,
-                      width: size.width * scale, height: size.height * scale)
-    }
-}
-
-extension Comparable {
-    func clamped(to limits: ClosedRange<Self>) -> Self {
-        return min(max(self, limits.lowerBound), limits.upperBound)
-    }
-}
-
-extension Kingfisher where Base: Image {
-    
-    func beginContext(size: CGSize, scale: CGFloat) -> CGContext? {
-        #if os(macOS)
-            guard let rep = NSBitmapImageRep(
-                bitmapDataPlanes: nil,
-                pixelsWide: Int(size.width),
-                pixelsHigh: Int(size.height),
-                bitsPerSample: cgImage?.bitsPerComponent ?? 8,
-                samplesPerPixel: 4,
-                hasAlpha: true,
-                isPlanar: false,
-                colorSpaceName: .calibratedRGB,
-                bytesPerRow: 0,
-                bitsPerPixel: 0) else
-            {
-                assertionFailure("[Kingfisher] Image representation cannot be created.")
-                return nil
-            }
-            rep.size = size
-            NSGraphicsContext.saveGraphicsState()
-            guard let context = NSGraphicsContext(bitmapImageRep: rep) else {
-                assertionFailure("[Kingfisher] Image contenxt cannot be created.")
-                return nil
-            }
-            
-            NSGraphicsContext.current = context
-            return context.cgContext
-        #else
-            UIGraphicsBeginImageContextWithOptions(size, false, scale)
-            let context = UIGraphicsGetCurrentContext()
-            context?.scaleBy(x: 1.0, y: -1.0)
-            context?.translateBy(x: 0, y: -size.height)
-            return context
-        #endif
-    }
-    
-    func endContext() {
-        #if os(macOS)
-            NSGraphicsContext.restoreGraphicsState()
-        #else
-            UIGraphicsEndImageContext()
-        #endif
-    }
-    
-    func draw(cgImage: CGImage?, to size: CGSize, draw: ()->()) -> Image {
-        #if os(macOS)
-        guard let rep = NSBitmapImageRep(
-            bitmapDataPlanes: nil,
-            pixelsWide: Int(size.width),
-            pixelsHigh: Int(size.height),
-            bitsPerSample: cgImage?.bitsPerComponent ?? 8,
-            samplesPerPixel: 4,
-            hasAlpha: true,
-            isPlanar: false,
-            colorSpaceName: .calibratedRGB,
-            bytesPerRow: 0,
-            bitsPerPixel: 0) else
-        {
-            assertionFailure("[Kingfisher] Image representation cannot be created.")
-            return base
-        }
-        rep.size = size
-        
-        NSGraphicsContext.saveGraphicsState()
-        
-        let context = NSGraphicsContext(bitmapImageRep: rep)
-        NSGraphicsContext.current = context
-        draw()
-        NSGraphicsContext.restoreGraphicsState()
-        
-        let outputImage = Image(size: size)
-        outputImage.addRepresentation(rep)
-        return outputImage
-        #else
-            
-        UIGraphicsBeginImageContextWithOptions(size, false, scale)
-        defer { UIGraphicsEndImageContext() }
-        draw()
-        return UIGraphicsGetImageFromCurrentImageContext() ?? base
-        
-        #endif
-    }
-    
-    #if os(macOS)
-    func fixedForRetinaPixel(cgImage: CGImage, to size: CGSize) -> Image {
-        
-        let image = Image(cgImage: cgImage, size: base.size)
-        let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: size)
-        
-        return draw(cgImage: cgImage, to: self.size) {
-            image.draw(in: rect, from: NSRect.zero, operation: .copy, fraction: 1.0)
-        }
-    }
-    #endif
-}
-
-extension Float {
-    var isEven: Bool {
-        return truncatingRemainder(dividingBy: 2.0) == 0
-    }
-}
-
-#if os(macOS)
-extension NSBezierPath {
-    convenience init(roundedRect rect: NSRect, topLeftRadius: CGFloat, topRightRadius: CGFloat,
-         bottomLeftRadius: CGFloat, bottomRightRadius: CGFloat)
-    {
-        self.init()
-        
-        let maxCorner = min(rect.width, rect.height) / 2
-        
-        let radiusTopLeft = min(maxCorner, max(0, topLeftRadius))
-        let radiusTopRight = min(maxCorner, max(0, topRightRadius))
-        let radiusBottomLeft = min(maxCorner, max(0, bottomLeftRadius))
-        let radiusBottomRight = min(maxCorner, max(0, bottomRightRadius))
-        
-        guard !NSIsEmptyRect(rect) else {
-            return
-        }
-        
-        let topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect));
-        let topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect));
-        let bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect));
-        
-        move(to: NSMakePoint(NSMidX(rect), NSMaxY(rect)))
-        appendArc(from: topLeft, to: rect.origin, radius: radiusTopLeft)
-        appendArc(from: rect.origin, to: bottomRight, radius: radiusBottomLeft)
-        appendArc(from: bottomRight, to: topRight, radius: radiusBottomRight)
-        appendArc(from: topRight, to: topLeft, radius: radiusTopRight)
-        close()
-    }
-    
-    convenience init(roundedRect rect: NSRect, byRoundingCorners corners: RectCorner, radius: CGFloat) {
-        let radiusTopLeft = corners.contains(.topLeft) ? radius : 0
-        let radiusTopRight = corners.contains(.topRight) ? radius : 0
-        let radiusBottomLeft = corners.contains(.bottomLeft) ? radius : 0
-        let radiusBottomRight = corners.contains(.bottomRight) ? radius : 0
-        
-        self.init(roundedRect: rect, topLeftRadius: radiusTopLeft, topRightRadius: radiusTopRight,
-                  bottomLeftRadius: radiusBottomLeft, bottomRightRadius: radiusBottomRight)
-    }
-}
-    
-#else
-extension RectCorner {
-    var uiRectCorner: UIRectCorner {
-        
-        var result: UIRectCorner = []
-        
-        if self.contains(.topLeft) { result.insert(.topLeft) }
-        if self.contains(.topRight) { result.insert(.topRight) }
-        if self.contains(.bottomLeft) { result.insert(.bottomLeft) }
-        if self.contains(.bottomRight) { result.insert(.bottomRight) }
-        
-        return result
-    }
-}
-#endif
-

+ 0 - 742
Example/Pods/Kingfisher/Sources/ImageCache.swift

@@ -1,742 +0,0 @@
-//
-//  ImageCache.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 15/4/6.
-//
-//  Copyright (c) 2018 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.
-
-#if os(macOS)
-import AppKit
-#else
-import UIKit
-#endif
-
-extension Notification.Name {
-    /**
-     This notification will be sent when the disk cache got cleaned either there are cached files expired or the total size exceeding the max allowed size. The manually invoking of `clearDiskCache` method will not trigger this notification.
-     
-     The `object` of this notification is the `ImageCache` object which sends the notification.
-     
-     A list of removed hashes (files) could be retrieved by accessing the array under `KingfisherDiskCacheCleanedHashKey` key in `userInfo` of the notification object you received. By checking the array, you could know the hash codes of files are removed.
-     
-     The main purpose of this notification is supplying a chance to maintain some necessary information on the cached files. See [this wiki](https://github.com/onevcat/Kingfisher/wiki/How-to-implement-ETag-based-304-(Not-Modified)-handling-in-Kingfisher) for a use case on it.
-     */
-    public static let KingfisherDidCleanDiskCache = Notification.Name.init("com.onevcat.Kingfisher.KingfisherDidCleanDiskCache")
-}
-
-/**
-Key for array of cleaned hashes in `userInfo` of `KingfisherDidCleanDiskCacheNotification`.
-*/
-public let KingfisherDiskCacheCleanedHashKey = "com.onevcat.Kingfisher.cleanedHash"
-
-/// It represents a task of retrieving image. You can call `cancel` on it to stop the process.
-public typealias RetrieveImageDiskTask = DispatchWorkItem
-
-/**
-Cache type of a cached image.
-
-- None:   The image is not cached yet when retrieving it.
-- Memory: The image is cached in memory.
-- Disk:   The image is cached in disk.
-*/
-public enum CacheType {
-    case none, memory, disk
-    
-    public var cached: Bool {
-        switch self {
-        case .memory, .disk: return true
-        case .none: return false
-        }
-    }
-}
-
-/// `ImageCache` represents both the memory and disk cache system of Kingfisher. 
-/// While a default image cache object will be used if you prefer the extension methods of Kingfisher, 
-/// you can create your own cache object and configure it as your need. You could use an `ImageCache`
-/// object to manipulate memory and disk cache for Kingfisher.
-open class ImageCache {
-
-    //Memory
-    fileprivate let memoryCache = NSCache<NSString, AnyObject>()
-    
-    /// The largest cache cost of memory cache. The total cost is pixel count of 
-    /// all cached images in memory.
-    /// Default is unlimited. Memory cache will be purged automatically when a 
-    /// memory warning notification is received.
-    open var maxMemoryCost: UInt = 0 {
-        didSet {
-            self.memoryCache.totalCostLimit = Int(maxMemoryCost)
-        }
-    }
-    
-    //Disk
-    fileprivate let ioQueue: DispatchQueue
-    fileprivate var fileManager: FileManager!
-    
-    ///The disk cache location.
-    public let diskCachePath: String
-  
-    /// The default file extension appended to cached files.
-    open var pathExtension: String?
-    
-    /// The longest time duration in second of the cache being stored in disk. 
-    /// Default is 1 week (60 * 60 * 24 * 7 seconds).
-    /// Setting this to a negative value will make the disk cache never expiring.
-    open var maxCachePeriodInSecond: TimeInterval = 60 * 60 * 24 * 7 //Cache exists for 1 week
-    
-    /// The largest disk size can be taken for the cache. It is the total 
-    /// allocated size of cached files in bytes.
-    /// Default is no limit.
-    open var maxDiskCacheSize: UInt = 0
-    
-    fileprivate let processQueue: DispatchQueue
-    
-    /// The default cache.
-    public static let `default` = ImageCache(name: "default")
-    
-    /// Closure that defines the disk cache path from a given path and cacheName.
-    public typealias DiskCachePathClosure = (String?, String) -> String
-    
-    /// The default DiskCachePathClosure
-    public final class func defaultDiskCachePathClosure(path: String?, cacheName: String) -> String {
-        let dstPath = path ?? NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!
-        return (dstPath as NSString).appendingPathComponent(cacheName)
-    }
-    
-    /**
-    Init method. Passing a name for the cache. It represents a cache folder in the memory and disk.
-    
-    - parameter name: Name of the cache. It will be used as the memory cache name and the disk cache folder name 
-                      appending to the cache path. This value should not be an empty string.
-    - parameter path: Optional - Location of cache path on disk. If `nil` is passed in (the default value),
-                      the `.cachesDirectory` in of your app will be used.
-    - parameter diskCachePathClosure: Closure that takes in an optional initial path string and generates
-                      the final disk cache path. You could use it to fully customize your cache path.
-    */
-    public init(name: String,
-                path: String? = nil,
-                diskCachePathClosure: DiskCachePathClosure = ImageCache.defaultDiskCachePathClosure)
-    {
-        
-        if name.isEmpty {
-            fatalError("[Kingfisher] You should specify a name for the cache. A cache with empty name is not permitted.")
-        }
-        
-        let cacheName = "com.onevcat.Kingfisher.ImageCache.\(name)"
-        memoryCache.name = cacheName
-        
-        diskCachePath = diskCachePathClosure(path, cacheName)
-        
-        let ioQueueName = "com.onevcat.Kingfisher.ImageCache.ioQueue.\(name)"
-        ioQueue = DispatchQueue(label: ioQueueName)
-        
-        let processQueueName = "com.onevcat.Kingfisher.ImageCache.processQueue.\(name)"
-        processQueue = DispatchQueue(label: processQueueName, attributes: .concurrent)
-        
-        ioQueue.sync { fileManager = FileManager() }
-        
-#if !os(macOS) && !os(watchOS)
-        
-        #if swift(>=4.2)
-        let memoryNotification = UIApplication.didReceiveMemoryWarningNotification
-        let terminateNotification = UIApplication.willTerminateNotification
-        let enterbackgroundNotification = UIApplication.didEnterBackgroundNotification
-        #else
-        let memoryNotification = NSNotification.Name.UIApplicationDidReceiveMemoryWarning
-        let terminateNotification = NSNotification.Name.UIApplicationWillTerminate
-        let enterbackgroundNotification = NSNotification.Name.UIApplicationDidEnterBackground
-        #endif
-        
-        NotificationCenter.default.addObserver(
-            self, selector: #selector(clearMemoryCache), name: memoryNotification, object: nil)
-        NotificationCenter.default.addObserver(
-            self, selector: #selector(cleanExpiredDiskCache), name: terminateNotification, object: nil)
-        NotificationCenter.default.addObserver(
-            self, selector: #selector(backgroundCleanExpiredDiskCache), name: enterbackgroundNotification, object: nil)
-#endif
-    }
-    
-    deinit {
-        NotificationCenter.default.removeObserver(self)
-    }
-
-
-    // MARK: - Store & Remove
-
-    /**
-    Store an image to cache. It will be saved to both memory and disk. It is an async operation.
-    
-    - parameter image:             The image to be stored.
-    - parameter original:          The original data of the image.
-                                   Kingfisher will use it to check the format of the image and optimize cache size on disk.
-                                   If `nil` is supplied, the image data will be saved as a normalized PNG file.
-                                   It is strongly suggested to supply it whenever possible, to get a better performance and disk usage.
-    - parameter key:               Key for the image.
-    - parameter identifier:        The identifier of processor used. If you are using a processor for the image, pass the identifier of
-                                   processor to it.
-                                   This identifier will be used to generate a corresponding key for the combination of `key` and processor.
-    - parameter toDisk:            Whether this image should be cached to disk or not. If false, the image will be only cached in memory.
-    - parameter completionHandler: Called when store operation completes.
-    */
-    open func store(_ image: Image,
-                      original: Data? = nil,
-                      forKey key: String,
-                      processorIdentifier identifier: String = "",
-                      cacheSerializer serializer: CacheSerializer = DefaultCacheSerializer.default,
-                      toDisk: Bool = true,
-                      completionHandler: (() -> Void)? = nil)
-    {
-        
-        let computedKey = key.computedKey(with: identifier)
-        memoryCache.setObject(image, forKey: computedKey as NSString, cost: image.kf.imageCost)
-
-        func callHandlerInMainQueue() {
-            if let handler = completionHandler {
-                DispatchQueue.main.async {
-                    handler()
-                }
-            }
-        }
-        
-        if toDisk {
-            ioQueue.async {
-                
-                if let data = serializer.data(with: image, original: original) {
-                    if !self.fileManager.fileExists(atPath: self.diskCachePath) {
-                        do {
-                            try self.fileManager.createDirectory(atPath: self.diskCachePath, withIntermediateDirectories: true, attributes: nil)
-                        } catch _ {}
-                    }
-                    
-                    self.fileManager.createFile(atPath: self.cachePath(forComputedKey: computedKey), contents: data, attributes: nil)
-                }
-                callHandlerInMainQueue()
-            }
-        } else {
-            callHandlerInMainQueue()
-        }
-    }
-    
-    /**
-    Remove the image for key for the cache. It will be opted out from both memory and disk. 
-    It is an async operation.
-    
-    - parameter key:               Key for the image.
-    - parameter identifier:        The identifier of processor used. If you are using a processor for the image, pass the identifier of processor to it.
-                                   This identifier will be used to generate a corresponding key for the combination of `key` and processor.
-    - parameter fromMemory:        Whether this image should be removed from memory or not. If false, the image won't be removed from memory.
-    - parameter fromDisk:          Whether this image should be removed from disk or not. If false, the image won't be removed from disk.
-    - parameter completionHandler: Called when removal operation completes.
-    */
-    open func removeImage(forKey key: String,
-                          processorIdentifier identifier: String = "",
-                          fromMemory: Bool = true,
-                          fromDisk: Bool = true,
-                          completionHandler: (() -> Void)? = nil)
-    {
-        let computedKey = key.computedKey(with: identifier)
-
-        if fromMemory {
-            memoryCache.removeObject(forKey: computedKey as NSString)
-        }
-        
-        func callHandlerInMainQueue() {
-            if let handler = completionHandler {
-                DispatchQueue.main.async {
-                    handler()
-                }
-            }
-        }
-        
-        if fromDisk {
-            ioQueue.async{
-                do {
-                    try self.fileManager.removeItem(atPath: self.cachePath(forComputedKey: computedKey))
-                } catch _ {}
-                callHandlerInMainQueue()
-            }
-        } else {
-            callHandlerInMainQueue()
-        }
-    }
-
-    // MARK: - Get data from cache
-
-    /**
-    Get an image for a key from memory or disk.
-    
-    - parameter key:               Key for the image.
-    - parameter options:           Options of retrieving image. If you need to retrieve an image which was 
-                                   stored with a specified `ImageProcessor`, pass the processor in the option too.
-    - parameter completionHandler: Called when getting operation completes with image result and cached type of 
-                                   this image. If there is no such key cached, the image will be `nil`.
-    
-    - returns: The retrieving task.
-    */
-    @discardableResult
-    open func retrieveImage(forKey key: String,
-                               options: KingfisherOptionsInfo?,
-                     completionHandler: ((Image?, CacheType) -> Void)?) -> RetrieveImageDiskTask?
-    {
-        // No completion handler. Not start working and early return.
-        guard let completionHandler = completionHandler else {
-            return nil
-        }
-        
-        var block: RetrieveImageDiskTask?
-        let options = options ?? KingfisherEmptyOptionsInfo
-        let imageModifier = options.imageModifier
-
-        if let image = self.retrieveImageInMemoryCache(forKey: key, options: options) {
-            options.callbackDispatchQueue.safeAsync {
-                completionHandler(imageModifier.modify(image), .memory)
-            }
-        } else if options.fromMemoryCacheOrRefresh { // Only allows to get images from memory cache.
-            options.callbackDispatchQueue.safeAsync {
-                completionHandler(nil, .none)
-            }
-        } else {
-            var sSelf: ImageCache! = self
-            block = DispatchWorkItem(block: {
-                // Begin to load image from disk
-                if let image = sSelf.retrieveImageInDiskCache(forKey: key, options: options) {
-                    if options.backgroundDecode {
-                        sSelf.processQueue.async {
-
-                            let result = image.kf.decoded
-                            
-                            sSelf.store(result,
-                                        forKey: key,
-                                        processorIdentifier: options.processor.identifier,
-                                        cacheSerializer: options.cacheSerializer,
-                                        toDisk: false,
-                                        completionHandler: nil)
-                            options.callbackDispatchQueue.safeAsync {
-                                completionHandler(imageModifier.modify(result), .disk)
-                                sSelf = nil
-                            }
-                        }
-                    } else {
-                        sSelf.store(image,
-                                    forKey: key,
-                                    processorIdentifier: options.processor.identifier,
-                                    cacheSerializer: options.cacheSerializer,
-                                    toDisk: false,
-                                    completionHandler: nil
-                        )
-                        options.callbackDispatchQueue.safeAsync {
-                            completionHandler(imageModifier.modify(image), .disk)
-                            sSelf = nil
-                        }
-                    }
-                } else {
-                    // No image found from either memory or disk
-                    options.callbackDispatchQueue.safeAsync {
-                        completionHandler(nil, .none)
-                        sSelf = nil
-                    }
-                }
-            })
-            
-            sSelf.ioQueue.async(execute: block!)
-        }
-    
-        return block
-    }
-    
-    /**
-    Get an image for a key from memory.
-    
-    - parameter key:     Key for the image.
-    - parameter options: Options of retrieving image. If you need to retrieve an image which was 
-                         stored with a specified `ImageProcessor`, pass the processor in the option too.
-    - returns: The image object if it is cached, or `nil` if there is no such key in the cache.
-    */
-    open func retrieveImageInMemoryCache(forKey key: String, options: KingfisherOptionsInfo? = nil) -> Image? {
-        
-        let options = options ?? KingfisherEmptyOptionsInfo
-        let computedKey = key.computedKey(with: options.processor.identifier)
-        
-        return memoryCache.object(forKey: computedKey as NSString) as? Image
-    }
-    
-    /**
-    Get an image for a key from disk.
-    
-    - parameter key:     Key for the image.
-    - parameter options: Options of retrieving image. If you need to retrieve an image which was
-                         stored with a specified `ImageProcessor`, pass the processor in the option too.
-
-    - returns: The image object if it is cached, or `nil` if there is no such key in the cache.
-    */
-    open func retrieveImageInDiskCache(forKey key: String, options: KingfisherOptionsInfo? = nil) -> Image? {
-        
-        let options = options ?? KingfisherEmptyOptionsInfo
-        let computedKey = key.computedKey(with: options.processor.identifier)
-        
-        return diskImage(forComputedKey: computedKey, serializer: options.cacheSerializer, options: options)
-    }
-
-
-    // MARK: - Clear & Clean
-
-    /**
-    Clear memory cache.
-    */
-    @objc public func clearMemoryCache() {
-        memoryCache.removeAllObjects()
-    }
-    
-    /**
-    Clear disk cache. This is an async operation.
-    
-    - parameter completionHander: Called after the operation completes.
-    */
-    open func clearDiskCache(completion handler: (()->())? = nil) {
-        ioQueue.async {
-            do {
-                try self.fileManager.removeItem(atPath: self.diskCachePath)
-                try self.fileManager.createDirectory(atPath: self.diskCachePath, withIntermediateDirectories: true, attributes: nil)
-            } catch _ { }
-            
-            if let handler = handler {
-                DispatchQueue.main.async {
-                    handler()
-                }
-            }
-        }
-    }
-    
-    /**
-    Clean expired disk cache. This is an async operation.
-    */
-    @objc fileprivate func cleanExpiredDiskCache() {
-        cleanExpiredDiskCache(completion: nil)
-    }
-    
-    /**
-    Clean expired disk cache. This is an async operation.
-    
-    - parameter completionHandler: Called after the operation completes.
-    */
-    open func cleanExpiredDiskCache(completion handler: (()->())? = nil) {
-        
-        // Do things in concurrent io queue
-        ioQueue.async {
-            
-            var (URLsToDelete, diskCacheSize, cachedFiles) = self.travelCachedFiles(onlyForCacheSize: false)
-            
-            for fileURL in URLsToDelete {
-                do {
-                    try self.fileManager.removeItem(at: fileURL)
-                } catch _ { }
-            }
-                
-            if self.maxDiskCacheSize > 0 && diskCacheSize > self.maxDiskCacheSize {
-                let targetSize = self.maxDiskCacheSize / 2
-                    
-                // Sort files by last modify date. We want to clean from the oldest files.
-                let sortedFiles = cachedFiles.keysSortedByValue {
-                    resourceValue1, resourceValue2 -> Bool in
-                    
-                    if let date1 = resourceValue1.contentAccessDate,
-                       let date2 = resourceValue2.contentAccessDate
-                    {
-                        return date1.compare(date2) == .orderedAscending
-                    }
-                    
-                    // Not valid date information. This should not happen. Just in case.
-                    return true
-                }
-                
-                for fileURL in sortedFiles {
-                    
-                    do {
-                        try self.fileManager.removeItem(at: fileURL)
-                    } catch { }
-                        
-                    URLsToDelete.append(fileURL)
-                    
-                    if let fileSize = cachedFiles[fileURL]?.totalFileAllocatedSize {
-                        diskCacheSize -= UInt(fileSize)
-                    }
-                    
-                    if diskCacheSize < targetSize {
-                        break
-                    }
-                }
-            }
-                
-            DispatchQueue.main.async {
-                
-                if URLsToDelete.count != 0 {
-                    let cleanedHashes = URLsToDelete.map { $0.lastPathComponent }
-                    NotificationCenter.default.post(name: .KingfisherDidCleanDiskCache, object: self, userInfo: [KingfisherDiskCacheCleanedHashKey: cleanedHashes])
-                }
-                
-                handler?()
-            }
-        }
-    }
-    
-    fileprivate func travelCachedFiles(onlyForCacheSize: Bool) -> (urlsToDelete: [URL], diskCacheSize: UInt, cachedFiles: [URL: URLResourceValues]) {
-        
-        let diskCacheURL = URL(fileURLWithPath: diskCachePath)
-        let resourceKeys: Set<URLResourceKey> = [.isDirectoryKey, .contentAccessDateKey, .totalFileAllocatedSizeKey]
-        let expiredDate: Date? = (maxCachePeriodInSecond < 0) ? nil : Date(timeIntervalSinceNow: -maxCachePeriodInSecond)
-        
-        var cachedFiles = [URL: URLResourceValues]()
-        var urlsToDelete = [URL]()
-        var diskCacheSize: UInt = 0
-
-        for fileUrl in (try? fileManager.contentsOfDirectory(at: diskCacheURL, includingPropertiesForKeys: Array(resourceKeys), options: .skipsHiddenFiles)) ?? [] {
-
-            do {
-                let resourceValues = try fileUrl.resourceValues(forKeys: resourceKeys)
-                // If it is a Directory. Continue to next file URL.
-                if resourceValues.isDirectory == true {
-                    continue
-                }
-
-                // If this file is expired, add it to URLsToDelete
-                if !onlyForCacheSize,
-                    let expiredDate = expiredDate,
-                    let lastAccessData = resourceValues.contentAccessDate,
-                    (lastAccessData as NSDate).laterDate(expiredDate) == expiredDate
-                {
-                    urlsToDelete.append(fileUrl)
-                    continue
-                }
-
-                if let fileSize = resourceValues.totalFileAllocatedSize {
-                    diskCacheSize += UInt(fileSize)
-                    if !onlyForCacheSize {
-                        cachedFiles[fileUrl] = resourceValues
-                    }
-                }
-            } catch _ { }
-        }
-
-        return (urlsToDelete, diskCacheSize, cachedFiles)
-    }
-
-#if !os(macOS) && !os(watchOS)
-    /**
-    Clean expired disk cache when app in background. This is an async operation.
-    In most cases, you should not call this method explicitly. 
-    It will be called automatically when `UIApplicationDidEnterBackgroundNotification` received.
-    */
-    @objc public func backgroundCleanExpiredDiskCache() {
-        // if 'sharedApplication()' is unavailable, then return
-        guard let sharedApplication = Kingfisher<UIApplication>.shared else { return }
-
-        func endBackgroundTask(_ task: inout UIBackgroundTaskIdentifier) {
-            sharedApplication.endBackgroundTask(task)
-            #if swift(>=4.2)
-            task = UIBackgroundTaskIdentifier.invalid
-            #else
-            task = UIBackgroundTaskInvalid
-            #endif
-        }
-        
-        var backgroundTask: UIBackgroundTaskIdentifier!
-        backgroundTask = sharedApplication.beginBackgroundTask {
-            endBackgroundTask(&backgroundTask!)
-        }
-        
-        cleanExpiredDiskCache {
-            endBackgroundTask(&backgroundTask!)
-        }
-    }
-#endif
-
-
-    // MARK: - Check cache status
-    
-    /// Cache type for checking whether an image is cached for a key in current cache.
-    ///
-    /// - Parameters:
-    ///   - key: Key for the image.
-    ///   - identifier: Processor identifier which used for this image. Default is empty string.
-    /// - Returns: A `CacheType` instance which indicates the cache status. `.none` means the image is not in cache yet.
-    open func imageCachedType(forKey key: String, processorIdentifier identifier: String = "") -> CacheType {
-        let computedKey = key.computedKey(with: identifier)
-        
-        if memoryCache.object(forKey: computedKey as NSString) != nil {
-            return .memory
-        }
-        
-        let filePath = cachePath(forComputedKey: computedKey)
-        
-        var diskCached = false
-        ioQueue.sync {
-            diskCached = fileManager.fileExists(atPath: filePath)
-        }
-        
-        if diskCached {
-            return .disk
-        }
-        
-        return .none
-    }
-    
-    /**
-    Get the hash for the key. This could be used for matching files.
-    
-    - parameter key:        The key which is used for caching.
-    - parameter identifier: The identifier of processor used. If you are using a processor for the image, pass the identifier of processor to it.
-    
-     - returns: Corresponding hash.
-    */
-    open func hash(forKey key: String, processorIdentifier identifier: String = "") -> String {
-        let computedKey = key.computedKey(with: identifier)
-        return cacheFileName(forComputedKey: computedKey)
-    }
-    
-    /**
-    Calculate the disk size taken by cache. 
-    It is the total allocated size of the cached files in bytes.
-    
-    - parameter completionHandler: Called with the calculated size when finishes.
-    */
-    open func calculateDiskCacheSize(completion handler: @escaping ((_ size: UInt) -> Void)) {
-        ioQueue.async {
-            let (_, diskCacheSize, _) = self.travelCachedFiles(onlyForCacheSize: true)
-            DispatchQueue.main.async {
-                handler(diskCacheSize)
-            }
-        }
-    }
-    
-    /**
-    Get the cache path for the key.
-    It is useful for projects with UIWebView or anyone that needs access to the local file path.
-    
-    i.e. Replace the `<img src='path_for_key'>` tag in your HTML.
-     
-    - Note: This method does not guarantee there is an image already cached in the path. It just returns the path
-      that the image should be.
-      You could use `isImageCached(forKey:)` method to check whether the image is cached under that key.
-    */
-    open func cachePath(forKey key: String, processorIdentifier identifier: String = "") -> String {
-        let computedKey = key.computedKey(with: identifier)
-        return cachePath(forComputedKey: computedKey)
-    }
-
-    open func cachePath(forComputedKey key: String) -> String {
-        let fileName = cacheFileName(forComputedKey: key)
-        return (diskCachePath as NSString).appendingPathComponent(fileName)
-    }
-}
-
-// MARK: - Internal Helper
-extension ImageCache {
-  
-    func diskImage(forComputedKey key: String, serializer: CacheSerializer, options: KingfisherOptionsInfo) -> Image? {
-        if let data = diskImageData(forComputedKey: key) {
-            return serializer.image(with: data, options: options)
-        } else {
-            return nil
-        }
-    }
-    
-    func diskImageData(forComputedKey key: String) -> Data? {
-        let filePath = cachePath(forComputedKey: key)
-        return (try? Data(contentsOf: URL(fileURLWithPath: filePath)))
-    }
-    
-    func cacheFileName(forComputedKey key: String) -> String {
-        if let ext = self.pathExtension {
-          return (key.kf.md5 as NSString).appendingPathExtension(ext)!
-        }
-        return key.kf.md5
-    }
-}
-
-// MARK: - Deprecated
-extension ImageCache {
-    /**
-     *  Cache result for checking whether an image is cached for a key.
-     */
-    @available(*, deprecated,
-    message: "CacheCheckResult is deprecated. Use imageCachedType(forKey:processorIdentifier:) API instead.")
-    public struct CacheCheckResult {
-        public let cached: Bool
-        public let cacheType: CacheType?
-    }
-    
-    /**
-     Check whether an image is cached for a key.
-     
-     - parameter key: Key for the image.
-     
-     - returns: The check result.
-     */
-    @available(*, deprecated,
-    message: "Use imageCachedType(forKey:processorIdentifier:) instead. CacheCheckResult.none indicates not being cached.",
-    renamed: "imageCachedType(forKey:processorIdentifier:)")
-    open func isImageCached(forKey key: String, processorIdentifier identifier: String = "") -> CacheCheckResult {
-        let result = imageCachedType(forKey: key, processorIdentifier: identifier)
-        switch result {
-        case .memory, .disk:
-            return CacheCheckResult(cached: true, cacheType: result)
-        case .none:
-            return CacheCheckResult(cached: false, cacheType: nil)
-        }
-    }
-}
-
-extension Kingfisher where Base: Image {
-    var imageCost: Int {
-        return images == nil ?
-            Int(size.height * size.width * scale * scale) :
-            Int(size.height * size.width * scale * scale) * images!.count
-    }
-}
-
-extension Dictionary {
-    func keysSortedByValue(_ isOrderedBefore: (Value, Value) -> Bool) -> [Key] {
-        return Array(self).sorted{ isOrderedBefore($0.1, $1.1) }.map{ $0.0 }
-    }
-}
-
-#if !os(macOS) && !os(watchOS)
-// MARK: - For App Extensions
-extension UIApplication: KingfisherCompatible { }
-extension Kingfisher where Base: UIApplication {
-    public static var shared: UIApplication? {
-        let selector = NSSelectorFromString("sharedApplication")
-        guard Base.responds(to: selector) else { return nil }
-        return Base.perform(selector).takeUnretainedValue() as? UIApplication
-    }
-}
-#endif
-
-extension String {
-    func computedKey(with identifier: String) -> String {
-        if identifier.isEmpty {
-            return self
-        } else {
-            return appending("@\(identifier)")
-        }
-    }
-}

+ 0 - 677
Example/Pods/Kingfisher/Sources/ImageDownloader.swift

@@ -1,677 +0,0 @@
-//
-//  ImageDownloader.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 15/4/6.
-//
-//  Copyright (c) 2018 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.
-
-#if os(macOS)
-import AppKit
-#else
-import UIKit
-#endif
-
-/// Progress update block of downloader.
-public typealias ImageDownloaderProgressBlock = DownloadProgressBlock
-
-/// Completion block of downloader.
-public typealias ImageDownloaderCompletionHandler = ((_ image: Image?, _ error: NSError?, _ url: URL?, _ originalData: Data?) -> Void)
-
-/// Download task.
-public struct RetrieveImageDownloadTask {
-    let internalTask: URLSessionDataTask
-    
-    /// Downloader by which this task is initialized.
-    public private(set) weak var ownerDownloader: ImageDownloader?
-
-    
-    /// Cancel this download task. It will trigger the completion handler with an NSURLErrorCancelled error.
-    /// If you want to cancel all downloading tasks, call `cancelAll()` of `ImageDownloader` instance.
-    public func cancel() {
-        ownerDownloader?.cancel(self)
-    }
-    
-    /// The original request URL of this download task.
-    public var url: URL? {
-        return internalTask.originalRequest?.url
-    }
-    
-    /// The relative priority of this download task. 
-    /// It represents the `priority` property of the internal `NSURLSessionTask` of this download task.
-    /// The value for it is between 0.0~1.0. Default priority is value of 0.5.
-    /// See documentation on `priority` of `NSURLSessionTask` for more about it.
-    public var priority: Float {
-        get {
-            return internalTask.priority
-        }
-        set {
-            internalTask.priority = newValue
-        }
-    }
-}
-
-///The code of errors which `ImageDownloader` might encountered.
-public enum KingfisherError: Int {
-    
-    /// badData: The downloaded data is not an image or the data is corrupted.
-    case badData = 10000
-    
-    /// notModified: The remote server responded a 304 code. No image data downloaded.
-    case notModified = 10001
-    
-    /// The HTTP status code in response is not valid. If an invalid
-    /// code error received, you could check the value under `KingfisherErrorStatusCodeKey` 
-    /// in `userInfo` to see the code.
-    case invalidStatusCode = 10002
-    
-    /// notCached: The image requested is not in cache but .onlyFromCache is activated.
-    case notCached = 10003
-    
-    /// The URL is invalid.
-    case invalidURL = 20000
-    
-    /// The downloading task is cancelled before started.
-    case downloadCancelledBeforeStarting = 30000
-}
-
-/// Key will be used in the `userInfo` of `.invalidStatusCode`
-public let KingfisherErrorStatusCodeKey = "statusCode"
-
-/// Protocol of `ImageDownloader`.
-public protocol ImageDownloaderDelegate: AnyObject {
-    /**
-     Called when the `ImageDownloader` object will start downloading an image from specified URL.
-     
-     - parameter downloader: The `ImageDownloader` object finishes the downloading.
-     - parameter url:        URL of the original request URL.
-     - parameter response:   The request object for the download process.
-     */
-    func imageDownloader(_ downloader: ImageDownloader, willDownloadImageForURL url: URL, with request: URLRequest?)
-    
-    /**
-     Called when the `ImageDownloader` completes a downloading request with success or failure.
-     
-     - parameter downloader: The `ImageDownloader` object finishes the downloading.
-     - parameter url:        URL of the original request URL.
-     - parameter response:   The response object of the downloading process.
-     - parameter error:      The error in case of failure.
-     */
-    func imageDownloader(_ downloader: ImageDownloader, didFinishDownloadingImageForURL url: URL, with response: URLResponse?, error: Error?)
-    
-    /**
-    Called when the `ImageDownloader` object successfully downloaded an image from specified URL.
-    
-    - parameter downloader: The `ImageDownloader` object finishes the downloading.
-    - parameter image:      Downloaded image.
-    - parameter url:        URL of the original request URL.
-    - parameter response:   The response object of the downloading process.
-    */
-    func imageDownloader(_ downloader: ImageDownloader, didDownload image: Image, for url: URL, with response: URLResponse?)
-    
-    /**
-    Check if a received HTTP status code is valid or not. 
-    By default, a status code between 200 to 400 (excluded) is considered as valid.
-    If an invalid code is received, the downloader will raise an .invalidStatusCode error.
-    It has a `userInfo` which includes this statusCode and localizedString error message.
-     
-    - parameter code: The received HTTP status code.
-    - parameter downloader: The `ImageDownloader` object asking for validate status code.
-     
-    - returns: Whether this HTTP status code is valid or not.
-     
-    - Note: If the default 200 to 400 valid code does not suit your need, 
-            you can implement this method to change that behavior.
-    */
-    func isValidStatusCode(_ code: Int, for downloader: ImageDownloader) -> Bool
-    
-    /**
-     Called when the `ImageDownloader` object successfully downloaded image data from specified URL.
-     
-     - parameter downloader: The `ImageDownloader` object finishes data downloading.
-     - parameter data:       Downloaded data.
-     - parameter url:        URL of the original request URL.
-     
-     - returns: The data from which Kingfisher should use to create an image.
-     
-     - Note: This callback can be used to preprocess raw image data
-             before creation of UIImage instance (i.e. decrypting or verification).
-     */
-    func imageDownloader(_ downloader: ImageDownloader, didDownload data: Data, for url: URL) -> Data?
-}
-
-extension ImageDownloaderDelegate {
-    
-    public func imageDownloader(_ downloader: ImageDownloader, willDownloadImageForURL url: URL, with request: URLRequest?) {}
-    
-    public func imageDownloader(_ downloader: ImageDownloader, didFinishDownloadingImageForURL url: URL, with response: URLResponse?, error: Error?) {}
-    
-    public func imageDownloader(_ downloader: ImageDownloader, didDownload image: Image, for url: URL, with response: URLResponse?) {}
-    
-    public func isValidStatusCode(_ code: Int, for downloader: ImageDownloader) -> Bool {
-        return (200..<400).contains(code)
-    }
-    public func imageDownloader(_ downloader: ImageDownloader, didDownload data: Data, for url: URL) -> Data? {
-        return data
-    }
-}
-
-/// Protocol indicates that an authentication challenge could be handled.
-public protocol AuthenticationChallengeResponsable: AnyObject {
-    /**
-     Called when an session level authentication challenge is received.
-     This method provide a chance to handle and response to the authentication challenge before downloading could start.
-     
-     - parameter downloader:        The downloader which receives this challenge.
-     - parameter challenge:         An object that contains the request for authentication.
-     - parameter completionHandler: A handler that your delegate method must call.
-     
-     - Note: This method is a forward from `URLSessionDelegate.urlSession(:didReceiveChallenge:completionHandler:)`. Please refer to the document of it in `URLSessionDelegate`.
-     */
-    func downloader(_ downloader: ImageDownloader, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
-
-    /**
-     Called when an session level authentication challenge is received.
-     This method provide a chance to handle and response to the authentication challenge before downloading could start.
-     
-     - parameter downloader:        The downloader which receives this challenge.
-     - parameter task:              The task whose request requires authentication.
-     - parameter challenge:         An object that contains the request for authentication.
-     - parameter completionHandler: A handler that your delegate method must call.
-     
-     - Note: This method is a forward from `URLSessionTaskDelegate.urlSession(:task:didReceiveChallenge:completionHandler:)`. Please refer to the document of it in `URLSessionTaskDelegate`.
-     */
-    func downloader(_ downloader: ImageDownloader, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
-}
-
-extension AuthenticationChallengeResponsable {
-    
-    func downloader(_ downloader: ImageDownloader, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
-    
-        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
-            if let trustedHosts = downloader.trustedHosts, trustedHosts.contains(challenge.protectionSpace.host) {
-                let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
-                completionHandler(.useCredential, credential)
-                return
-            }
-        }
-        
-        completionHandler(.performDefaultHandling, nil)
-    }
-    
-    func downloader(_ downloader: ImageDownloader, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
-        
-        completionHandler(.performDefaultHandling, nil)
-    }
-
-}
-
-/// `ImageDownloader` represents a downloading manager for requesting the image with a URL from server.
-open class ImageDownloader {
-    
-    class ImageFetchLoad {
-        var contents = [(callback: CallbackPair, options: KingfisherOptionsInfo)]()
-        var responseData = NSMutableData()
-
-        var downloadTaskCount = 0
-        var downloadTask: RetrieveImageDownloadTask?
-        var cancelSemaphore: DispatchSemaphore?
-    }
-    
-    // MARK: - Public property
-    /// The duration before the download is timeout. Default is 15 seconds.
-    open var downloadTimeout: TimeInterval = 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. It only will be used if you don't specify the `authenticationChallengeResponder`. 
-    /// If `authenticationChallengeResponder` is set, this property will be ignored and the implementation of `authenticationChallengeResponder` will be used instead.
-    open var trustedHosts: Set<String>?
-    
-    /// Use this to set supply a configuration for the downloader. By default, NSURLSessionConfiguration.ephemeralSessionConfiguration() will be used. 
-    /// You could change the configuration before a downloading task starts. A configuration without persistent storage for caches is requested for downloader working correctly.
-    open var sessionConfiguration = URLSessionConfiguration.ephemeral {
-        didSet {
-            session?.invalidateAndCancel()
-            session = URLSession(configuration: sessionConfiguration, delegate: sessionHandler, delegateQueue: nil)
-        }
-    }
-    
-    /// Whether the download requests should use pipline or not. Default is false.
-    open var requestsUsePipelining = false
-    
-    fileprivate let sessionHandler: ImageDownloaderSessionHandler
-    fileprivate var session: URLSession?
-    
-    /// Delegate of this `ImageDownloader` object. See `ImageDownloaderDelegate` protocol for more.
-    open weak var delegate: ImageDownloaderDelegate?
-    
-    /// A responder for authentication challenge. 
-    /// Downloader will forward the received authentication challenge for the downloading session to this responder.
-    open weak var authenticationChallengeResponder: AuthenticationChallengeResponsable?
-    
-    // MARK: - Internal property
-    let barrierQueue: DispatchQueue
-    let processQueue: DispatchQueue
-    let cancelQueue: DispatchQueue
-    
-    typealias CallbackPair = (progressBlock: ImageDownloaderProgressBlock?, completionHandler: ImageDownloaderCompletionHandler?)
-    
-    var fetchLoads = [URL: ImageFetchLoad]()
-    
-    // MARK: - Public method
-    /// The default downloader.
-    public static let `default` = ImageDownloader(name: "default")
-    
-    /**
-    Init a downloader with name.
-    
-    - parameter name: The name for the downloader. It should not be empty.
-    */
-    public init(name: String) {
-        if name.isEmpty {
-            fatalError("[Kingfisher] You should specify a name for the downloader. A downloader with empty name is not permitted.")
-        }
-        
-        barrierQueue = DispatchQueue(label: "com.onevcat.Kingfisher.ImageDownloader.Barrier.\(name)", attributes: .concurrent)
-        processQueue = DispatchQueue(label: "com.onevcat.Kingfisher.ImageDownloader.Process.\(name)", attributes: .concurrent)
-        cancelQueue = DispatchQueue(label: "com.onevcat.Kingfisher.ImageDownloader.Cancel.\(name)")
-        
-        sessionHandler = ImageDownloaderSessionHandler(name: name)
-
-        // Provide a default implement for challenge responder.
-        authenticationChallengeResponder = sessionHandler
-        session = URLSession(configuration: sessionConfiguration, delegate: sessionHandler, delegateQueue: .main)
-    }
-    
-    deinit {
-        session?.invalidateAndCancel()
-    }
-    
-    func fetchLoad(for url: URL) -> ImageFetchLoad? {
-        var fetchLoad: ImageFetchLoad?
-        barrierQueue.sync(flags: .barrier) { fetchLoad = fetchLoads[url] }
-        return fetchLoad
-    }
-    
-    /**
-     Download an image with a URL and option.
-     
-     - parameter url:               Target URL.
-     - parameter retrieveImageTask: The task to cooperate with cache. Pass `nil` if you are not trying to use downloader and cache.
-     - parameter options:           The options could control download behavior. See `KingfisherOptionsInfo`.
-     - parameter progressBlock:     Called when the download progress updated.
-     - parameter completionHandler: Called when the download progress finishes.
-     
-     - returns: A downloading task. You could call `cancel` on it to stop the downloading process.
-     */
-    @discardableResult
-    open func downloadImage(with url: URL,
-                       retrieveImageTask: RetrieveImageTask? = nil,
-                       options: KingfisherOptionsInfo? = nil,
-                       progressBlock: ImageDownloaderProgressBlock? = nil,
-                       completionHandler: ImageDownloaderCompletionHandler? = nil) -> RetrieveImageDownloadTask?
-    {
-        if let retrieveImageTask = retrieveImageTask, retrieveImageTask.cancelledBeforeDownloadStarting {
-            completionHandler?(nil, NSError(domain: KingfisherErrorDomain, code: KingfisherError.downloadCancelledBeforeStarting.rawValue, userInfo: nil), nil, nil)
-            return nil
-        }
-        
-        let timeout = self.downloadTimeout == 0.0 ? 15.0 : self.downloadTimeout
-        
-        // We need to set the URL as the load key. So before setup progress, we need to ask the `requestModifier` for a final URL.
-        var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: timeout)
-        request.httpShouldUsePipelining = requestsUsePipelining
-
-        if let modifier = options?.modifier {
-            guard let r = modifier.modified(for: request) else {
-                completionHandler?(nil, NSError(domain: KingfisherErrorDomain, code: KingfisherError.downloadCancelledBeforeStarting.rawValue, userInfo: nil), nil, nil)
-                return nil
-            }
-            request = r
-        }
-        
-        // There is a possibility that request modifier changed the url to `nil` or empty.
-        guard let url = request.url, !url.absoluteString.isEmpty else {
-            completionHandler?(nil, NSError(domain: KingfisherErrorDomain, code: KingfisherError.invalidURL.rawValue, userInfo: nil), nil, nil)
-            return nil
-        }
-        
-        var downloadTask: RetrieveImageDownloadTask?
-        setup(progressBlock: progressBlock, with: completionHandler, for: url, options: options) {(session, fetchLoad) -> Void in
-            if fetchLoad.downloadTask == nil {
-                let dataTask = session.dataTask(with: request)
-                
-                fetchLoad.downloadTask = RetrieveImageDownloadTask(internalTask: dataTask, ownerDownloader: self)
-                
-                dataTask.priority = options?.downloadPriority ?? URLSessionTask.defaultPriority
-                self.delegate?.imageDownloader(self, willDownloadImageForURL: url, with: request)
-                dataTask.resume()
-                
-                // Hold self while the task is executing.
-                self.sessionHandler.downloadHolder = self
-            }
-            
-            fetchLoad.downloadTaskCount += 1
-            downloadTask = fetchLoad.downloadTask
-            
-            retrieveImageTask?.downloadTask = downloadTask
-        }
-        return downloadTask
-    }
-    
-}
-
-// MARK: - Download method
-extension ImageDownloader {
-    
-    // A single key may have multiple callbacks. Only download once.
-    func setup(progressBlock: ImageDownloaderProgressBlock?, with completionHandler: ImageDownloaderCompletionHandler?, for url: URL, options: KingfisherOptionsInfo?, started: @escaping ((URLSession, ImageFetchLoad) -> Void)) {
-
-        func prepareFetchLoad() {
-            barrierQueue.sync(flags: .barrier) {
-                let loadObjectForURL = fetchLoads[url] ?? ImageFetchLoad()
-                let callbackPair = (progressBlock: progressBlock, completionHandler: completionHandler)
-                
-                loadObjectForURL.contents.append((callbackPair, options ?? KingfisherEmptyOptionsInfo))
-                
-                fetchLoads[url] = loadObjectForURL
-                
-                if let session = session {
-                    started(session, loadObjectForURL)
-                }
-            }
-        }
-        
-        if let fetchLoad = fetchLoad(for: url), fetchLoad.downloadTaskCount == 0 {
-            if fetchLoad.cancelSemaphore == nil {
-                fetchLoad.cancelSemaphore = DispatchSemaphore(value: 0)
-            }
-            cancelQueue.async {
-                _ = fetchLoad.cancelSemaphore?.wait(timeout: .distantFuture)
-                fetchLoad.cancelSemaphore = nil
-                prepareFetchLoad()
-            }
-        } else {
-            prepareFetchLoad()
-        }
-    }
-    
-    private func cancelTaskImpl(_ task: RetrieveImageDownloadTask, fetchLoad: ImageFetchLoad? = nil, ignoreTaskCount: Bool = false) {
-        
-        func getFetchLoad(from task: RetrieveImageDownloadTask) -> ImageFetchLoad? {
-            guard let URL = task.internalTask.originalRequest?.url,
-                  let imageFetchLoad = self.fetchLoads[URL] else
-            {
-                return nil
-            }
-            return imageFetchLoad
-        }
-        
-        guard let imageFetchLoad = fetchLoad ?? getFetchLoad(from: task) else {
-            return
-        }
-
-        imageFetchLoad.downloadTaskCount -= 1
-        if ignoreTaskCount || imageFetchLoad.downloadTaskCount == 0 {
-            task.internalTask.cancel()
-        }
-    }
-    
-    func cancel(_ task: RetrieveImageDownloadTask) {
-        barrierQueue.sync(flags: .barrier) { cancelTaskImpl(task) }
-    }
-    
-    /// Cancel all downloading tasks. It will trigger the completion handlers for all not-yet-finished
-    /// downloading tasks with an NSURLErrorCancelled error.
-    ///
-    /// If you need to only cancel a certain task, call `cancel()` on the `RetrieveImageDownloadTask`
-    /// returned by the downloading methods.
-    public func cancelAll() {
-        barrierQueue.sync(flags: .barrier) {
-            fetchLoads.forEach { v in
-                let fetchLoad = v.value
-                guard let task = fetchLoad.downloadTask else { return }
-                cancelTaskImpl(task, fetchLoad: fetchLoad, ignoreTaskCount: true)
-            }
-        }
-    }
-}
-
-// MARK: - NSURLSessionDataDelegate
-
-/// Delegate class for `NSURLSessionTaskDelegate`.
-/// The session object will hold its delegate until it gets invalidated.
-/// If we use `ImageDownloader` as the session delegate, it will not be released.
-/// So we need an additional handler to break the retain cycle.
-// See https://github.com/onevcat/Kingfisher/issues/235
-final class ImageDownloaderSessionHandler: NSObject, URLSessionDataDelegate, AuthenticationChallengeResponsable {
-
-    private let downloaderQueue: DispatchQueue
-
-    // The holder will keep downloader not released while a data task is being executed.
-    // It will be set when the task started, and reset when the task finished.
-    private var _downloadHolder: ImageDownloader?
-    var downloadHolder: ImageDownloader? {
-        get {
-            return downloaderQueue.sync { _downloadHolder }
-        }
-        set {
-            downloaderQueue.sync { _downloadHolder = newValue }
-        }
-    }
-
-    init(name: String) {
-        downloaderQueue = DispatchQueue(label: "com.onevcat.Kingfisher.ImageDownloader.SessionHandler.\(name)")
-        super.init()
-    }
-    
-    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
-        
-        guard let downloader = downloadHolder else {
-            completionHandler(.cancel)
-            return
-        }
-        
-        var disposition = URLSession.ResponseDisposition.allow
-        
-        if let statusCode = (response as? HTTPURLResponse)?.statusCode,
-           let url = dataTask.originalRequest?.url,
-            !(downloader.delegate ?? downloader).isValidStatusCode(statusCode, for: downloader)
-        {
-            let error = NSError(domain: KingfisherErrorDomain,
-                                code: KingfisherError.invalidStatusCode.rawValue,
-                                userInfo: [KingfisherErrorStatusCodeKey: statusCode, NSLocalizedDescriptionKey: HTTPURLResponse.localizedString(forStatusCode: statusCode)])
-            
-            // Needs to be called before callCompletionHandlerFailure() because it removes downloadHolder
-            if let downloader = downloadHolder {
-                downloader.delegate?.imageDownloader(downloader, didFinishDownloadingImageForURL: url, with: response, error: error)
-            }
-            
-            callCompletionHandlerFailure(error: error, url: url)
-            disposition = .cancel
-        }
-        
-        completionHandler(disposition)
-    }
-    
-    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
-
-        guard let downloader = downloadHolder else {
-            return
-        }
-
-        if let url = dataTask.originalRequest?.url, let fetchLoad = downloader.fetchLoad(for: url) {
-            fetchLoad.responseData.append(data)
-            
-            if let expectedLength = dataTask.response?.expectedContentLength {
-                for content in fetchLoad.contents {
-                    DispatchQueue.main.async {
-                        content.callback.progressBlock?(Int64(fetchLoad.responseData.length), expectedLength)
-                    }
-                }
-            }
-        }
-    }
-    
-    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
-        
-        guard let url = task.originalRequest?.url else {
-            return
-        }
-        
-        if let downloader = downloadHolder {
-            downloader.delegate?.imageDownloader(downloader, didFinishDownloadingImageForURL: url, with: task.response, error: error)
-        }
-        
-        guard error == nil else {
-            callCompletionHandlerFailure(error: error!, url: url)
-            return
-        }
-        
-        processImage(for: task, url: url)
-    }
-    
-    /**
-    This method is exposed since the compiler requests. Do not call it.
-    */
-    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
-        guard let downloader = downloadHolder else {
-            return
-        }
-        
-        downloader.authenticationChallengeResponder?.downloader(downloader, didReceive: challenge, completionHandler: completionHandler)
-    }
-    
-    func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
-        guard let downloader = downloadHolder else {
-            return
-        }
-        
-        downloader.authenticationChallengeResponder?.downloader(downloader, task: task, didReceive: challenge, completionHandler: completionHandler)
-    }
-    
-    private func cleanFetchLoad(for url: URL) {
-        guard let downloader = downloadHolder else {
-            return
-        }
-
-        downloader.barrierQueue.sync(flags: .barrier) {
-            downloader.fetchLoads.removeValue(forKey: url)
-            if downloader.fetchLoads.isEmpty {
-                downloadHolder = nil
-            }
-        }
-    }
-    
-    private func callCompletionHandlerFailure(error: Error, url: URL) {
-        guard let downloader = downloadHolder, let fetchLoad = downloader.fetchLoad(for: url) else {
-            return
-        }
-        
-        // We need to clean the fetch load first, before actually calling completion handler.
-        cleanFetchLoad(for: url)
-        
-        var leftSignal: Int
-        repeat {
-            leftSignal = fetchLoad.cancelSemaphore?.signal() ?? 0
-        } while leftSignal != 0
-        
-        for content in fetchLoad.contents {
-            content.options.callbackDispatchQueue.safeAsync {
-                content.callback.completionHandler?(nil, error as NSError, url, nil)
-            }
-        }
-    }
-    
-    private func processImage(for task: URLSessionTask, url: URL) {
-
-        guard let downloader = downloadHolder else {
-            return
-        }
-        
-        // We are on main queue when receiving this.
-        downloader.processQueue.async {
-            
-            guard let fetchLoad = downloader.fetchLoad(for: url) else {
-                return
-            }
-            
-            self.cleanFetchLoad(for: url)
-            
-            let data: Data?
-            let fetchedData = fetchLoad.responseData as Data
-            
-            if let delegate = downloader.delegate {
-                data = delegate.imageDownloader(downloader, didDownload: fetchedData, for: url)
-            } else {
-                data = fetchedData
-            }
-            
-            // Cache the processed images. So we do not need to re-process the image if using the same processor.
-            // Key is the identifier of processor.
-            var imageCache: [String: Image] = [:]
-            for content in fetchLoad.contents {
-                
-                let options = content.options
-                let completionHandler = content.callback.completionHandler
-                let callbackQueue = options.callbackDispatchQueue
-                
-                let processor = options.processor
-                var image = imageCache[processor.identifier]
-                if let data = data, image == nil {
-                    image = processor.process(item: .data(data), options: options)
-                    // Add the processed image to cache. 
-                    // If `image` is nil, nothing will happen (since the key is not existing before).
-                    imageCache[processor.identifier] = image
-                }
-                
-                if let image = image {
-
-                    downloader.delegate?.imageDownloader(downloader, didDownload: image, for: url, with: task.response)
-
-                    let imageModifier = options.imageModifier
-                    let finalImage = imageModifier.modify(image)
-
-                    if options.backgroundDecode {
-                        let decodedImage = finalImage.kf.decoded
-                        callbackQueue.safeAsync { completionHandler?(decodedImage, nil, url, data) }
-                    } else {
-                        callbackQueue.safeAsync { completionHandler?(finalImage, nil, url, data) }
-                    }
-                    
-                } else {
-                    if let res = task.response as? HTTPURLResponse , res.statusCode == 304 {
-                        let notModified = NSError(domain: KingfisherErrorDomain, code: KingfisherError.notModified.rawValue, userInfo: nil)
-                        completionHandler?(nil, notModified, url, nil)
-                        continue
-                    }
-                    
-                    let badData = NSError(domain: KingfisherErrorDomain, code: KingfisherError.badData.rawValue, userInfo: nil)
-                    callbackQueue.safeAsync { completionHandler?(nil, badData, url, nil) }
-                }
-            }
-        }
-    }
-}
-
-// Placeholder. For retrieving extension methods of ImageDownloaderDelegate
-extension ImageDownloader: ImageDownloaderDelegate {}
-

+ 0 - 191
Example/Pods/Kingfisher/Sources/ImageModifier.swift

@@ -1,191 +0,0 @@
-//
-//  ImageModifier.swift
-//  Kingfisher
-//
-//  Created by Ethan Gill on 2017/11/28.
-//
-//  Copyright (c) 2018 Ethan Gill <ethan.gill@me.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.
-
-import Foundation
-
-/// An `ImageModifier` can be used to change properties on an Image in between
-/// cache serialization and use of the image.
-public protocol ImageModifier {
-    /// Modify an input `Image`.
-    ///
-    /// - parameter image:   Image which will be modified by `self`
-    ///
-    /// - returns: The modified image.
-    ///
-    /// - Note: The return value will be unmodified if modifying is not possible on
-    ///         the current platform.
-    /// - Note: Most modifiers support UIImage or NSImage, but not CGImage.
-    func modify(_ image: Image) -> Image
-}
-
-extension ImageModifier {
-    func modify(_ image: Image?) -> Image? {
-        guard let image = image else {
-            return nil
-        }
-        return modify(image)
-    }
-}
-
-typealias ModifierImp = ((Image) -> Image)
-
-fileprivate struct GeneralModifier: ImageModifier {
-    let identifier: String
-    let m: ModifierImp
-    func modify(_ image: Image) -> Image {
-        return m(image)
-    }
-}
-
-/// The default modifier.
-/// Does nothing and returns the image it was given
-public struct DefaultImageModifier: ImageModifier {
-
-    /// A default `DefaultImageModifier` which can be used everywhere.
-    public static let `default` = DefaultImageModifier()
-
-    /// Initialize a `DefaultImageModifier`
-    private init() {}
-
-    /// Modify an input `Image`.
-    ///
-    /// - parameter image:   Image which will be modified by `self`
-    ///
-    /// - returns: The modified image.
-    ///
-    /// - Note: See documentation of `ImageModifier` protocol for more.
-    public func modify(_ image: Image) -> Image {
-        return image
-    }
-}
-
-/// A custom modifier.
-/// Can be initialized with a block to modify images in a custom way
-public struct AnyImageModifier: ImageModifier {
-
-    /// A block which modifies images, or returns the original image
-    /// if modification cannot be performed.
-    let block: (Image) -> Image
-
-    /// Initialize an `AnyImageModifier`
-    public init(modify: @escaping (Image) -> Image) {
-        block = modify
-    }
-
-    /// Modifies an input `Image` using this `AnyImageModifier`'s `block`.
-    ///
-    /// - parameter image:   Image which will be modified by `self`
-    ///
-    /// - returns: The modified image.
-    ///
-    /// - Note: See documentation of `ImageModifier` protocol for more.
-    public func modify(_ image: Image) -> Image {
-        return block(image)
-    }
-}
-
-#if os(iOS) || os(tvOS) || os(watchOS)
-import UIKit
-
-/// Modifier for setting the rendering mode of images.
-/// Only UI-based images are supported; if a non-UI image is passed in, the
-/// modifier will do nothing.
-public struct RenderingModeImageModifier: ImageModifier {
-
-    /// The rendering mode to apply to the image.
-    public let renderingMode: UIImage.RenderingMode
-
-    /// Initialize a `RenderingModeImageModifier`
-    ///
-    /// - parameter renderingMode: The rendering mode to apply to the image.
-    ///                            Default is .automatic
-    public init(renderingMode: UIImage.RenderingMode = .automatic) {
-        self.renderingMode = renderingMode
-    }
-
-    /// Modify an input `Image`.
-    ///
-    /// - parameter image:   Image which will be modified by `self`
-    ///
-    /// - returns: The modified image.
-    ///
-    /// - Note: See documentation of `ImageModifier` protocol for more.
-    public func modify(_ image: Image) -> Image {
-        return image.withRenderingMode(renderingMode)
-    }
-}
-
-/// Modifier for setting the `flipsForRightToLeftLayoutDirection` property of images.
-/// Only UI-based images are supported; if a non-UI image is passed in, the
-/// modifier will do nothing.
-public struct FlipsForRightToLeftLayoutDirectionImageModifier: ImageModifier {
-    /// Initialize a `FlipsForRightToLeftLayoutDirectionImageModifier`
-    ///
-    /// - Note: On versions of iOS lower than 9.0, the image will be returned
-    ///         unmodified.
-    public init() {}
-
-    /// Modify an input `Image`.
-    ///
-    /// - parameter image:   Image which will be modified by `self`
-    ///
-    /// - returns: The modified image.
-    ///
-    /// - Note: See documentation of `ImageModifier` protocol for more.
-    public func modify(_ image: Image) -> Image {
-        if #available(iOS 9.0, *) {
-            return image.imageFlippedForRightToLeftLayoutDirection()
-        } else {
-            return image
-        }
-    }
-}
-
-/// Modifier for setting the `alignmentRectInsets` property of images.
-/// Only UI-based images are supported; if a non-UI image is passed in, the
-/// modifier will do nothing.
-public struct AlignmentRectInsetsImageModifier: ImageModifier {
-
-    /// The alignment insets to apply to the image
-    public let alignmentInsets: UIEdgeInsets
-
-    /// Initialize a `AlignmentRectInsetsImageModifier`
-    public init(alignmentInsets: UIEdgeInsets) {
-        self.alignmentInsets = alignmentInsets
-    }
-
-    /// Modify an input `Image`.
-    ///
-    /// - parameter image:   Image which will be modified by `self`
-    ///
-    /// - returns: The modified image.
-    ///
-    /// - Note: See documentation of `ImageModifier` protocol for more.
-    public func modify(_ image: Image) -> Image {
-        return image.withAlignmentRectInsets(alignmentInsets)
-    }
-}
-#endif

+ 0 - 277
Example/Pods/Kingfisher/Sources/ImagePrefetcher.swift

@@ -1,277 +0,0 @@
-//
-//  ImagePrefetcher.swift
-//  Kingfisher
-//
-//  Created by Claire Knight <claire.knight@moggytech.co.uk> on 24/02/2016
-//
-//  Copyright (c) 2018 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.
-
-
-#if os(macOS)
-    import AppKit
-#else
-    import UIKit
-#endif
-
-
-/// Progress update block of prefetcher. 
-///
-/// - `skippedResources`: An array of resources that are already cached before the prefetching starting.
-/// - `failedResources`: An array of resources that fail to be downloaded. It could because of being cancelled while downloading, encountered an error when downloading or the download not being started at all.
-/// - `completedResources`: An array of resources that are downloaded and cached successfully.
-public typealias PrefetcherProgressBlock = ((_ skippedResources: [Resource], _ failedResources: [Resource], _ completedResources: [Resource]) -> Void)
-
-/// Completion block of prefetcher.
-///
-/// - `skippedResources`: An array of resources that are already cached before the prefetching starting.
-/// - `failedResources`: An array of resources that fail to be downloaded. It could because of being cancelled while downloading, encountered an error when downloading or the download not being started at all.
-/// - `completedResources`: An array of resources that are downloaded and cached successfully.
-public typealias PrefetcherCompletionHandler = ((_ skippedResources: [Resource], _ failedResources: [Resource], _ completedResources: [Resource]) -> Void)
-
-/// `ImagePrefetcher` represents a downloading manager for requesting many images via URLs, then caching them.
-/// This is useful when you know a list of image resources and want to download them before showing.
-public class ImagePrefetcher {
-    
-    /// The maximum concurrent downloads to use when prefetching images. Default is 5.
-    public var maxConcurrentDownloads = 5
-    
-    /// The dispatch queue to use for handling resource process so downloading does not occur on the main thread
-    /// This prevents stuttering when preloading images in a collection view or table view
-    private var prefetchQueue: DispatchQueue
-    
-    private let prefetchResources: [Resource]
-    private let optionsInfo: KingfisherOptionsInfo
-    private var progressBlock: PrefetcherProgressBlock?
-    private var completionHandler: PrefetcherCompletionHandler?
-    
-    private var tasks = [URL: RetrieveImageDownloadTask]()
-    
-    private var pendingResources: ArraySlice<Resource>
-    private var skippedResources = [Resource]()
-    private var completedResources = [Resource]()
-    private var failedResources = [Resource]()
-    
-    private var stopped = false
-    
-    // The created manager used for prefetch. We will use the helper method in manager.
-    private let manager: KingfisherManager
-    
-    private var finished: Bool {
-        return failedResources.count + skippedResources.count + completedResources.count == prefetchResources.count && self.tasks.isEmpty
-    }
-    
-    /**
-     Init an image prefetcher with an array of URLs.
-     
-     The prefetcher should be initiated with a list of prefetching targets. The URLs list is immutable. 
-     After you get a valid `ImagePrefetcher` object, you could call `start()` on it to begin the prefetching process.
-     The images already cached will be skipped without downloading again.
-     
-     - parameter urls:              The URLs which should be prefetched.
-     - parameter options:           A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
-     - parameter progressBlock:     Called every time an resource is downloaded, skipped or cancelled.
-     - parameter completionHandler: Called when the whole prefetching process finished.
-     
-     - Note: By default, the `ImageDownloader.defaultDownloader` and `ImageCache.defaultCache` will be used as 
-     the downloader and cache target respectively. You can specify another downloader or cache by using a customized `KingfisherOptionsInfo`.
-     Both the progress and completion block will be invoked in main thread. The `CallbackDispatchQueue` in `optionsInfo` will be ignored in this method.
-     */
-    public convenience init(urls: [URL],
-                         options: KingfisherOptionsInfo? = nil,
-                   progressBlock: PrefetcherProgressBlock? = nil,
-               completionHandler: PrefetcherCompletionHandler? = nil)
-    {
-        let resources: [Resource] = urls.map { $0 }
-        self.init(resources: resources, options: options, progressBlock: progressBlock, completionHandler: completionHandler)
-    }
-    
-    /**
-     Init an image prefetcher with an array of resources.
-     
-     The prefetcher should be initiated with a list of prefetching targets. The resources list is immutable.
-     After you get a valid `ImagePrefetcher` object, you could call `start()` on it to begin the prefetching process.
-     The images already cached will be skipped without downloading again.
-     
-     - parameter resources:         The resources which should be prefetched. See `Resource` type for more.
-     - parameter options:           A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
-     - parameter progressBlock:     Called every time an resource is downloaded, skipped or cancelled.
-     - parameter completionHandler: Called when the whole prefetching process finished.
-
-     - Note: By default, the `ImageDownloader.defaultDownloader` and `ImageCache.defaultCache` will be used as
-     the downloader and cache target respectively. You can specify another downloader or cache by using a customized `KingfisherOptionsInfo`.
-     Both the progress and completion block will be invoked in main thread. The `CallbackDispatchQueue` in `optionsInfo` will be ignored in this method.
-     */
-    public init(resources: [Resource],
-                  options: KingfisherOptionsInfo? = nil,
-            progressBlock: PrefetcherProgressBlock? = nil,
-        completionHandler: PrefetcherCompletionHandler? = nil)
-    {
-        prefetchResources = resources
-        pendingResources = ArraySlice(resources)
-        
-        // Set up the dispatch queue that all our work should occur on.
-        let prefetchQueueName = "com.onevcat.Kingfisher.PrefetchQueue"
-        prefetchQueue = DispatchQueue(label: prefetchQueueName)
-        
-        // We want all callbacks from our prefetch queue, so we should ignore the call back queue in options
-        var optionsInfoWithoutQueue = options?.removeAllMatchesIgnoringAssociatedValue(.callbackDispatchQueue(nil)) ?? KingfisherEmptyOptionsInfo
-        
-        // Add our own callback dispatch queue to make sure all callbacks are coming back in our expected queue
-        optionsInfoWithoutQueue.append(.callbackDispatchQueue(prefetchQueue))
-        
-        self.optionsInfo = optionsInfoWithoutQueue
-        
-        let cache = self.optionsInfo.targetCache ?? .default
-        let downloader = self.optionsInfo.downloader ?? .default
-        manager = KingfisherManager(downloader: downloader, cache: cache)
-        
-        self.progressBlock = progressBlock
-        self.completionHandler = completionHandler
-    }
-    
-    /**
-     Start to download the resources and cache them. This can be useful for background downloading
-     of assets that are required for later use in an app. This code will not try and update any UI
-     with the results of the process.
-     */
-    public func start()
-    {
-        // Since we want to handle the resources cancellation in the prefetch queue only.
-        prefetchQueue.async {
-            
-            guard !self.stopped else {
-                assertionFailure("You can not restart the same prefetcher. Try to create a new prefetcher.")
-                self.handleComplete()
-                return
-            }
-            
-            guard self.maxConcurrentDownloads > 0 else {
-                assertionFailure("There should be concurrent downloads value should be at least 1.")
-                self.handleComplete()
-                return
-            }
-            
-            guard self.prefetchResources.count > 0 else {
-                self.handleComplete()
-                return
-            }
-            
-            let initialConcurentDownloads = min(self.prefetchResources.count, self.maxConcurrentDownloads)
-            for _ in 0 ..< initialConcurentDownloads {
-                if let resource = self.pendingResources.popFirst() {
-                    self.startPrefetching(resource)
-                }
-            }
-        }
-    }
-
-   
-    /**
-     Stop current downloading progress, and cancel any future prefetching activity that might be occuring.
-     */
-    public func stop() {
-        prefetchQueue.async {
-            if self.finished { return }
-            self.stopped = true
-            self.tasks.values.forEach { $0.cancel() }
-        }
-    }
-    
-    func downloadAndCache(_ resource: Resource) {
-
-        let downloadTaskCompletionHandler: CompletionHandler = { (image, error, _, _) -> Void in
-            self.tasks.removeValue(forKey: resource.downloadURL)
-            if let _ = error {
-                self.failedResources.append(resource)
-            } else {
-                self.completedResources.append(resource)
-            }
-            
-            self.reportProgress()
-            if self.stopped {
-                if self.tasks.isEmpty {
-                    self.failedResources.append(contentsOf: self.pendingResources)
-                    self.handleComplete()
-                }
-            } else {
-                self.reportCompletionOrStartNext()
-            }
-        }
-        
-        let downloadTask = manager.downloadAndCacheImage(
-            with: resource.downloadURL,
-            forKey: resource.cacheKey,
-            retrieveImageTask: RetrieveImageTask(),
-            progressBlock: nil,
-            completionHandler: downloadTaskCompletionHandler,
-            options: optionsInfo)
-        
-        if let downloadTask = downloadTask {
-            tasks[resource.downloadURL] = downloadTask
-        }
-    }
-    
-    func append(cached resource: Resource) {
-        skippedResources.append(resource)
- 
-        reportProgress()
-        reportCompletionOrStartNext()
-    }
-    
-    func startPrefetching(_ resource: Resource)
-    {
-        if optionsInfo.forceRefresh {
-            downloadAndCache(resource)
-        } else {
-            let alreadyInCache = manager.cache.imageCachedType(forKey: resource.cacheKey,
-                                                             processorIdentifier: optionsInfo.processor.identifier).cached
-            if alreadyInCache {
-                append(cached: resource)
-            } else {
-                downloadAndCache(resource)
-            }
-        }
-    }
-    
-    func reportProgress() {
-        progressBlock?(skippedResources, failedResources, completedResources)
-    }
-    
-    func reportCompletionOrStartNext() {
-        prefetchQueue.async {
-            if let resource = self.pendingResources.popFirst() {
-                self.startPrefetching(resource)
-            } else {
-                guard self.tasks.isEmpty else { return }
-                self.handleComplete()
-            }
-        }
-    }
-    
-    func handleComplete() {
-        // The completion handler should be called on the main thread
-        DispatchQueue.main.safeAsync {
-            self.completionHandler?(self.skippedResources, self.failedResources, self.completedResources)
-            self.completionHandler = nil
-            self.progressBlock = nil
-        }
-    }
-}

+ 0 - 713
Example/Pods/Kingfisher/Sources/ImageProcessor.swift

@@ -1,713 +0,0 @@
-//
-//  ImageProcessor.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 2016/08/26.
-//
-//  Copyright (c) 2018 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.
-
-import Foundation
-import CoreGraphics
-
-#if os(macOS)
-import AppKit
-#endif
-
-/// The item which could be processed by an `ImageProcessor`
-///
-/// - image: Input image
-/// - data:  Input data
-public enum ImageProcessItem {
-    case image(Image)
-    case data(Data)
-}
-
-/// An `ImageProcessor` would be used to convert some downloaded data to an image.
-public protocol ImageProcessor {
-    /// Identifier of the processor. It will be used to identify the processor when 
-    /// caching and retrieving an image. You might want to make sure that processors with
-    /// same properties/functionality have the same identifiers, so correct processed images
-    /// could be retrieved with proper key.
-    /// 
-    /// - Note: Do not supply an empty string for a customized processor, which is already taken by
-    /// the `DefaultImageProcessor`. It is recommended to use a reverse domain name notation
-    /// string of your own for the identifier.
-    var identifier: String { get }
-    
-    /// Process an input `ImageProcessItem` item to an image for this processor.
-    ///
-    /// - parameter item:    Input item which will be processed by `self`
-    /// - parameter options: Options when processing the item.
-    ///
-    /// - returns: The processed image.
-    ///
-    /// - Note: The return value will be `nil` if processing failed while converting data to image.
-    ///         If input item is already an image and there is any errors in processing, the input 
-    ///         image itself will be returned.
-    /// - Note: Most processor only supports CG-based images. 
-    ///         watchOS is not supported for processors containing filter, the input image will be returned directly on watchOS.
-    func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image?
-}
-
-typealias ProcessorImp = ((ImageProcessItem, KingfisherOptionsInfo) -> Image?)
-
-public extension ImageProcessor {
-    
-    /// Append an `ImageProcessor` to another. The identifier of the new `ImageProcessor` 
-    /// will be "\(self.identifier)|>\(another.identifier)".
-    ///
-    /// - parameter another: An `ImageProcessor` you want to append to `self`.
-    ///
-    /// - returns: The new `ImageProcessor` will process the image in the order
-    ///            of the two processors concatenated.
-    public func append(another: ImageProcessor) -> ImageProcessor {
-        let newIdentifier = identifier.appending("|>\(another.identifier)")
-        return GeneralProcessor(identifier: newIdentifier) {
-            item, options in
-            if let image = self.process(item: item, options: options) {
-                return another.process(item: .image(image), options: options)
-            } else {
-                return nil
-            }
-        }
-    }
-}
-
-func ==(left: ImageProcessor, right: ImageProcessor) -> Bool {
-    return left.identifier == right.identifier
-}
-
-func !=(left: ImageProcessor, right: ImageProcessor) -> Bool {
-    return !(left == right)
-}
-
-fileprivate struct GeneralProcessor: ImageProcessor {
-    let identifier: String
-    let p: ProcessorImp
-    func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        return p(item, options)
-    }
-}
-
-/// The default processor. It convert the input data to a valid image.
-/// Images of .PNG, .JPEG and .GIF format are supported.
-/// If an image is given, `DefaultImageProcessor` will do nothing on it and just return that image.
-public struct DefaultImageProcessor: ImageProcessor {
-    
-    /// A default `DefaultImageProcessor` could be used across.
-    public static let `default` = DefaultImageProcessor()
-    
-    /// Identifier of the processor.
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public let identifier = ""
-    
-    /// Initialize a `DefaultImageProcessor`
-    public init() {}
-    
-    /// Process an input `ImageProcessItem` item to an image for this processor.
-    ///
-    /// - parameter item:    Input item which will be processed by `self`
-    /// - parameter options: Options when processing the item.
-    ///
-    /// - returns: The processed image.
-    /// 
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        switch item {
-        case .image(let image):
-            return image.kf.scaled(to: options.scaleFactor)
-        case .data(let data):
-            return Kingfisher<Image>.image(
-                data: data,
-                scale: options.scaleFactor,
-                preloadAllAnimationData: options.preloadAllAnimationData,
-                onlyFirstFrame: options.onlyLoadFirstFrame)
-        }
-    }
-}
-
-public struct RectCorner: OptionSet {
-    public let rawValue: Int
-    public static let topLeft = RectCorner(rawValue: 1 << 0)
-    public static let topRight = RectCorner(rawValue: 1 << 1)
-    public static let bottomLeft = RectCorner(rawValue: 1 << 2)
-    public static let bottomRight = RectCorner(rawValue: 1 << 3)
-    public static let all: RectCorner = [.topLeft, .topRight, .bottomLeft, .bottomRight]
-    
-    public init(rawValue: Int) {
-        self.rawValue = rawValue
-    }
-    
-    var cornerIdentifier: String {
-        if self == .all {
-            return ""
-        }
-        return "_corner(\(rawValue))"
-    }
-}
-
-#if !os(macOS)
-/// Processor for adding an blend mode to images. Only CG-based images are supported.
-public struct BlendImageProcessor: ImageProcessor {
-
-    /// Identifier of the processor.
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public let identifier: String
-
-    /// Blend Mode will be used to blend the input image.
-    public let blendMode: CGBlendMode
-    /// Alpha will be used when blend image.
-    public let alpha: CGFloat
-
-    /// Background color of the output image. If `nil`, it will stay transparent.
-    public let backgroundColor: Color?
-
-    /// Initialize an `BlendImageProcessor`
-    ///
-    /// - parameter blendMode:       Blend Mode will be used to blend the input image.
-    /// - parameter alpha:           Alpha will be used when blend image.
-    ///                              From 0.0 to 1.0. 1.0 means solid image, 0.0 means transparent image.
-    ///                              Default is 1.0.
-    /// - parameter backgroundColor: Background color to apply for the output image. Default is `nil`.
-    public init(blendMode: CGBlendMode, alpha: CGFloat = 1.0, backgroundColor: Color? = nil) {
-        self.blendMode = blendMode
-        self.alpha = alpha
-        self.backgroundColor = backgroundColor
-        var identifier = "com.onevcat.Kingfisher.BlendImageProcessor(\(blendMode.rawValue),\(alpha))"
-        if let color = backgroundColor {
-            identifier.append("_\(color.hex)")
-        }
-        self.identifier = identifier
-    }
-
-    /// Process an input `ImageProcessItem` item to an image for this processor.
-    ///
-    /// - parameter item:    Input item which will be processed by `self`
-    /// - parameter options: Options when processing the item.
-    ///
-    /// - returns: The processed image.
-    ///
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        switch item {
-        case .image(let image):
-            return image.kf.scaled(to: options.scaleFactor)
-                        .kf.image(withBlendMode: blendMode, alpha: alpha, backgroundColor: backgroundColor)
-        case .data(_):
-            return (DefaultImageProcessor.default >> self).process(item: item, options: options)
-        }
-    }
-}
-#endif
-
-#if os(macOS)
-/// Processor for adding an compositing operation to images. Only CG-based images are supported in macOS.
-public struct CompositingImageProcessor: ImageProcessor {
-
-    /// Identifier of the processor.
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public let identifier: String
-
-    /// Compositing operation will be used to the input image.
-    public let compositingOperation: NSCompositingOperation
-
-    /// Alpha will be used when compositing image.
-    public let alpha: CGFloat
-
-    /// Background color of the output image. If `nil`, it will stay transparent.
-    public let backgroundColor: Color?
-
-    /// Initialize an `CompositingImageProcessor`
-    ///
-    /// - parameter compositingOperation: Compositing operation will be used to the input image.
-    /// - parameter alpha:                Alpha will be used when compositing image.
-    ///                                   From 0.0 to 1.0. 1.0 means solid image, 0.0 means transparent image.
-    ///                                   Default is 1.0.
-    /// - parameter backgroundColor:      Background color to apply for the output image. Default is `nil`.
-    public init(compositingOperation: NSCompositingOperation,
-                alpha: CGFloat = 1.0,
-                backgroundColor: Color? = nil)
-    {
-        self.compositingOperation = compositingOperation
-        self.alpha = alpha
-        self.backgroundColor = backgroundColor
-        var identifier = "com.onevcat.Kingfisher.CompositingImageProcessor(\(compositingOperation.rawValue),\(alpha))"
-        if let color = backgroundColor {
-            identifier.append("_\(color.hex)")
-        }
-        self.identifier = identifier
-    }
-
-    /// Process an input `ImageProcessItem` item to an image for this processor.
-    ///
-    /// - parameter item:    Input item which will be processed by `self`
-    /// - parameter options: Options when processing the item.
-    ///
-    /// - returns: The processed image.
-    ///
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        switch item {
-        case .image(let image):
-            return image.kf.scaled(to: options.scaleFactor)
-                        .kf.image(withCompositingOperation: compositingOperation, alpha: alpha, backgroundColor: backgroundColor)
-        case .data(_):
-            return (DefaultImageProcessor.default >> self).process(item: item, options: options)
-        }
-    }
-}
-#endif
-
-/// Processor for making round corner images. Only CG-based images are supported in macOS, 
-/// if a non-CG image passed in, the processor will do nothing.
-public struct RoundCornerImageProcessor: ImageProcessor {
-    
-    /// Identifier of the processor.
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public let identifier: String
-
-    /// Corner radius will be applied in processing.
-    public let cornerRadius: CGFloat
-    
-    /// The target corners which will be applied rounding.
-    public let roundingCorners: RectCorner
-    
-    /// Target size of output image should be. If `nil`, the image will keep its original size after processing.
-    public let targetSize: CGSize?
-
-    /// Background color of the output image. If `nil`, it will stay transparent.
-    public let backgroundColor: Color?
-
-    /// Initialize a `RoundCornerImageProcessor`
-    ///
-    /// - parameter cornerRadius:    Corner radius will be applied in processing.
-    /// - parameter targetSize:      Target size of output image should be. If `nil`, 
-    ///                              the image will keep its original size after processing.
-    ///                              Default is `nil`.
-    /// - parameter corners:         The target corners which will be applied rounding. Default is `.all`.
-    /// - parameter backgroundColor: Background color to apply for the output image. Default is `nil`.
-    public init(cornerRadius: CGFloat, targetSize: CGSize? = nil, roundingCorners corners: RectCorner = .all, backgroundColor: Color? = nil) {
-        self.cornerRadius = cornerRadius
-        self.targetSize = targetSize
-        self.roundingCorners = corners
-        self.backgroundColor = backgroundColor
-
-        self.identifier = {
-            var identifier = ""
-
-            if let size = targetSize {
-                identifier = "com.onevcat.Kingfisher.RoundCornerImageProcessor(\(cornerRadius)_\(size)\(corners.cornerIdentifier))"
-            } else {
-                identifier = "com.onevcat.Kingfisher.RoundCornerImageProcessor(\(cornerRadius)\(corners.cornerIdentifier))"
-            }
-            if let backgroundColor = backgroundColor {
-                identifier += "_\(backgroundColor)"
-            }
-
-            return identifier
-        }()
-    }
-    
-    /// Process an input `ImageProcessItem` item to an image for this processor.
-    ///
-    /// - parameter item:    Input item which will be processed by `self`
-    /// - parameter options: Options when processing the item.
-    ///
-    /// - returns: The processed image.
-    ///
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        switch item {
-        case .image(let image):
-            let size = targetSize ?? image.kf.size
-            return image.kf.scaled(to: options.scaleFactor)
-                        .kf.image(withRoundRadius: cornerRadius, fit: size, roundingCorners: roundingCorners, backgroundColor: backgroundColor)
-        case .data(_):
-            return (DefaultImageProcessor.default >> self).process(item: item, options: options)
-        }
-    }
-}
-
-
-/// Specify how a size adjusts itself to fit a target size.
-///
-/// - none: Not scale the content.
-/// - aspectFit: Scale the content to fit the size of the view by maintaining the aspect ratio.
-/// - aspectFill: Scale the content to fill the size of the view
-public enum ContentMode {
-    case none
-    case aspectFit
-    case aspectFill
-}
-
-/// Processor for resizing images. Only CG-based images are supported in macOS.
-public struct ResizingImageProcessor: ImageProcessor {
-    
-    /// Identifier of the processor.
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public let identifier: String
-    
-    /// The reference size for resizing operation.
-    public let referenceSize: CGSize
-    
-    /// Target content mode of output image should be.
-    /// Default to ContentMode.none
-    public let targetContentMode: ContentMode
-    
-    /// Initialize a `ResizingImageProcessor`.
-    ///
-    /// - Parameters:
-    ///   - referenceSize: The reference size for resizing operation.
-    ///   - mode: Target content mode of output image should be.
-    ///
-    /// - Note:
-    ///   The instance of `ResizingImageProcessor` will follow its `mode` property
-    ///   and try to resizing the input images to fit or fill the `referenceSize`.
-    ///   That means if you are using a `mode` besides of `.none`, you may get an
-    ///   image with its size not be the same as the `referenceSize`.
-    ///
-    ///   **Example**: With input image size: {100, 200}, 
-    ///   `referenceSize`: {100, 100}, `mode`: `.aspectFit`,
-    ///   you will get an output image with size of {50, 100}, which "fit"s
-    ///   the `referenceSize`.
-    ///
-    ///   If you need an output image exactly to be a specified size, append or use
-    ///   a `CroppingImageProcessor`.
-    public init(referenceSize: CGSize, mode: ContentMode = .none) {
-        self.referenceSize = referenceSize
-        self.targetContentMode = mode
-        
-        if mode == .none {
-            self.identifier = "com.onevcat.Kingfisher.ResizingImageProcessor(\(referenceSize))"
-        } else {
-            self.identifier = "com.onevcat.Kingfisher.ResizingImageProcessor(\(referenceSize), \(mode))"
-        }
-    }
-    
-    /// Process an input `ImageProcessItem` item to an image for this processor.
-    ///
-    /// - parameter item:    Input item which will be processed by `self`
-    /// - parameter options: Options when processing the item.
-    ///
-    /// - returns: The processed image.
-    ///
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        switch item {
-        case .image(let image):
-            return image.kf.scaled(to: options.scaleFactor)
-                        .kf.resize(to: referenceSize, for: targetContentMode)
-        case .data(_):
-            return (DefaultImageProcessor.default >> self).process(item: item, options: options)
-        }
-    }
-}
-
-/// Processor for adding blur effect to images. `Accelerate.framework` is used underhood for 
-/// a better performance. A simulated Gaussian blur with specified blur radius will be applied.
-public struct BlurImageProcessor: ImageProcessor {
-    
-    /// Identifier of the processor.
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public let identifier: String
-    
-    /// Blur radius for the simulated Gaussian blur.
-    public let blurRadius: CGFloat
-
-    /// Initialize a `BlurImageProcessor`
-    ///
-    /// - parameter blurRadius: Blur radius for the simulated Gaussian blur.
-    public init(blurRadius: CGFloat) {
-        self.blurRadius = blurRadius
-        self.identifier = "com.onevcat.Kingfisher.BlurImageProcessor(\(blurRadius))"
-    }
-    
-    /// Process an input `ImageProcessItem` item to an image for this processor.
-    ///
-    /// - parameter item:    Input item which will be processed by `self`
-    /// - parameter options: Options when processing the item.
-    ///
-    /// - returns: The processed image.
-    ///
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        switch item {
-        case .image(let image):
-            let radius = blurRadius * options.scaleFactor
-            return image.kf.scaled(to: options.scaleFactor)
-                        .kf.blurred(withRadius: radius)
-        case .data(_):
-            return (DefaultImageProcessor.default >> self).process(item: item, options: options)
-        }
-    }
-}
-
-/// Processor for adding an overlay to images. Only CG-based images are supported in macOS.
-public struct OverlayImageProcessor: ImageProcessor {
-    
-    /// Identifier of the processor.
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public let identifier: String
-    
-    /// Overlay color will be used to overlay the input image.
-    public let overlay: Color
-    
-    /// Fraction will be used when overlay the color to image.
-    public let fraction: CGFloat
-    
-    /// Initialize an `OverlayImageProcessor`
-    ///
-    /// - parameter overlay:  Overlay color will be used to overlay the input image.
-    /// - parameter fraction: Fraction will be used when overlay the color to image. 
-    ///                       From 0.0 to 1.0. 0.0 means solid color, 1.0 means transparent overlay.
-    public init(overlay: Color, fraction: CGFloat = 0.5) {
-        self.overlay = overlay
-        self.fraction = fraction
-        self.identifier = "com.onevcat.Kingfisher.OverlayImageProcessor(\(overlay.hex)_\(fraction))"
-    }
-    
-    /// Process an input `ImageProcessItem` item to an image for this processor.
-    ///
-    /// - parameter item:    Input item which will be processed by `self`
-    /// - parameter options: Options when processing the item.
-    ///
-    /// - returns: The processed image.
-    ///
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        switch item {
-        case .image(let image):
-            return image.kf.scaled(to: options.scaleFactor)
-                        .kf.overlaying(with: overlay, fraction: fraction)
-        case .data(_):
-            return (DefaultImageProcessor.default >> self).process(item: item, options: options)
-        }
-    }
-}
-
-/// Processor for tint images with color. Only CG-based images are supported.
-public struct TintImageProcessor: ImageProcessor {
-    
-    /// Identifier of the processor.
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public let identifier: String
-    
-    /// Tint color will be used to tint the input image.
-    public let tint: Color
-    
-    /// Initialize a `TintImageProcessor`
-    ///
-    /// - parameter tint: Tint color will be used to tint the input image.
-    public init(tint: Color) {
-        self.tint = tint
-        self.identifier = "com.onevcat.Kingfisher.TintImageProcessor(\(tint.hex))"
-    }
-    
-    /// Process an input `ImageProcessItem` item to an image for this processor.
-    ///
-    /// - parameter item:    Input item which will be processed by `self`
-    /// - parameter options: Options when processing the item.
-    ///
-    /// - returns: The processed image.
-    ///
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        switch item {
-        case .image(let image):
-            return image.kf.scaled(to: options.scaleFactor)
-                        .kf.tinted(with: tint)
-        case .data(_):
-            return (DefaultImageProcessor.default >> self).process(item: item, options: options)
-        }
-    }
-}
-
-/// Processor for applying some color control to images. Only CG-based images are supported.
-/// watchOS is not supported.
-public struct ColorControlsProcessor: ImageProcessor {
-    
-    /// Identifier of the processor.
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public let identifier: String
-    
-    /// Brightness changing to image.
-    public let brightness: CGFloat
-    
-    /// Contrast changing to image.
-    public let contrast: CGFloat
-    
-    /// Saturation changing to image.
-    public let saturation: CGFloat
-    
-    /// InputEV changing to image.
-    public let inputEV: CGFloat
-    
-    /// Initialize a `ColorControlsProcessor`
-    ///
-    /// - parameter brightness: Brightness changing to image.
-    /// - parameter contrast:   Contrast changing to image.
-    /// - parameter saturation: Saturation changing to image.
-    /// - parameter inputEV:    InputEV changing to image.
-    public init(brightness: CGFloat, contrast: CGFloat, saturation: CGFloat, inputEV: CGFloat) {
-        self.brightness = brightness
-        self.contrast = contrast
-        self.saturation = saturation
-        self.inputEV = inputEV
-        self.identifier = "com.onevcat.Kingfisher.ColorControlsProcessor(\(brightness)_\(contrast)_\(saturation)_\(inputEV))"
-    }
-    
-    /// Process an input `ImageProcessItem` item to an image for this processor.
-    ///
-    /// - parameter item:    Input item which will be processed by `self`
-    /// - parameter options: Options when processing the item.
-    ///
-    /// - returns: The processed image.
-    ///
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        switch item {
-        case .image(let image):
-            return image.kf.scaled(to: options.scaleFactor)
-                        .kf.adjusted(brightness: brightness, contrast: contrast, saturation: saturation, inputEV: inputEV)
-        case .data(_):
-            return (DefaultImageProcessor.default >> self).process(item: item, options: options)
-        }
-    }
-}
-
-/// Processor for applying black and white effect to images. Only CG-based images are supported.
-/// watchOS is not supported.
-public struct BlackWhiteProcessor: ImageProcessor {
-    
-    /// Identifier of the processor.
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public let identifier = "com.onevcat.Kingfisher.BlackWhiteProcessor"
-    
-    /// Initialize a `BlackWhiteProcessor`
-    public init() {}
-    
-    /// Process an input `ImageProcessItem` item to an image for this processor.
-    ///
-    /// - parameter item:    Input item which will be processed by `self`
-    /// - parameter options: Options when processing the item.
-    ///
-    /// - returns: The processed image.
-    ///
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        return ColorControlsProcessor(brightness: 0.0, contrast: 1.0, saturation: 0.0, inputEV: 0.7)
-            .process(item: item, options: options)
-    }
-}
-
-/// Processor for cropping an image. Only CG-based images are supported.
-/// watchOS is not supported.
-public struct CroppingImageProcessor: ImageProcessor {
-    
-    /// Identifier of the processor.
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public let identifier: String
-    
-    /// Target size of output image should be.
-    public let size: CGSize
-    
-    /// Anchor point from which the output size should be calculate.
-    /// The anchor point is consisted by two values between 0.0 and 1.0.
-    /// It indicates a related point in current image. 
-    /// See `CroppingImageProcessor.init(size:anchor:)` for more.
-    public let anchor: CGPoint
-    
-    /// Initialize a `CroppingImageProcessor`
-    ///
-    /// - Parameters:
-    ///   - size: Target size of output image should be.
-    ///   - anchor: The anchor point from which the size should be calculated.
-    ///             Default is `CGPoint(x: 0.5, y: 0.5)`, which means the center of input image.
-    /// - Note:
-    ///   The anchor point is consisted by two values between 0.0 and 1.0.
-    ///   It indicates a related point in current image, eg: (0.0, 0.0) for top-left
-    ///   corner, (0.5, 0.5) for center and (1.0, 1.0) for bottom-right corner.
-    ///   The `size` property of `CroppingImageProcessor` will be used along with
-    ///   `anchor` to calculate a target rectangle in the size of image.
-    ///    
-    ///   The target size will be automatically calculated with a reasonable behavior.
-    ///   For example, when you have an image size of `CGSize(width: 100, height: 100)`,
-    ///   and a target size of `CGSize(width: 20, height: 20)`: 
-    ///   - with a (0.0, 0.0) anchor (top-left), the crop rect will be `{0, 0, 20, 20}`; 
-    ///   - with a (0.5, 0.5) anchor (center), it will be `{40, 40, 20, 20}`
-    ///   - while with a (1.0, 1.0) anchor (bottom-right), it will be `{80, 80, 20, 20}`
-    public init(size: CGSize, anchor: CGPoint = CGPoint(x: 0.5, y: 0.5)) {
-        self.size = size
-        self.anchor = anchor
-        self.identifier = "com.onevcat.Kingfisher.CroppingImageProcessor(\(size)_\(anchor))"
-    }
-    
-    /// Process an input `ImageProcessItem` item to an image for this processor.
-    ///
-    /// - parameter item:    Input item which will be processed by `self`
-    /// - parameter options: Options when processing the item.
-    ///
-    /// - returns: The processed image.
-    ///
-    /// - Note: See documentation of `ImageProcessor` protocol for more.
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        switch item {
-        case .image(let image):
-            return image.kf.scaled(to: options.scaleFactor)
-                        .kf.crop(to: size, anchorOn: anchor)
-        case .data(_): return (DefaultImageProcessor.default >> self).process(item: item, options: options)
-        }
-    }
-}
-
-/// Concatenate two `ImageProcessor`s. `ImageProcessor.appen(another:)` is used internally.
-///
-/// - parameter left:  First processor.
-/// - parameter right: Second processor.
-///
-/// - returns: The concatenated processor.
-public func >>(left: ImageProcessor, right: ImageProcessor) -> ImageProcessor {
-    return left.append(another: right)
-}
-
-extension Color {
-    var hex: String {
-        var r: CGFloat = 0
-        var g: CGFloat = 0
-        var b: CGFloat = 0
-        var a: CGFloat = 0
-
-        #if os(macOS)
-        (usingColorSpace(.sRGB) ?? self).getRed(&r, green: &g, blue: &b, alpha: &a)
-        #else
-        getRed(&r, green: &g, blue: &b, alpha: &a)
-        #endif
-
-        let rInt = Int(r * 255) << 24
-        let gInt = Int(g * 255) << 16
-        let bInt = Int(b * 255) << 8
-        let aInt = Int(a * 255)
-        
-        let rgba = rInt | gInt | bInt | aInt
-        
-        return String(format:"#%08x", rgba)
-    }
-}

+ 0 - 128
Example/Pods/Kingfisher/Sources/ImageTransition.swift

@@ -1,128 +0,0 @@
-//
-//  ImageTransition.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 15/9/18.
-//
-//  Copyright (c) 2018 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.
-
-#if os(macOS)
-// Not implemented for macOS and watchOS yet.
-    
-import AppKit
-
-/// Image transition is not supported on macOS.
-public enum ImageTransition {
-    case none
-    var duration: TimeInterval {
-        return 0
-    }
-}
-
-#elseif os(watchOS)
-import UIKit
-/// Image transition is not supported on watchOS.
-public enum ImageTransition {
-    case none
-    var duration: TimeInterval {
-        return 0
-    }
-}
-#else
-import UIKit
-
-/**
-Transition effect which will be used when an image downloaded and set by `UIImageView` extension API in Kingfisher.
-You can assign an enum value with transition duration as an item in `KingfisherOptionsInfo` 
-to enable the animation transition.
-
-Apple's UIViewAnimationOptions is used under the hood.
-For custom transition, you should specified your own transition options, animations and 
-completion handler as well.
-*/
-public enum ImageTransition {
-    ///  No animation transition.
-    case none
-    
-    /// Fade in the loaded image.
-    case fade(TimeInterval)
-
-    /// Flip from left transition.
-    case flipFromLeft(TimeInterval)
-
-    /// Flip from right transition.
-    case flipFromRight(TimeInterval)
-    
-    /// Flip from top transition.
-    case flipFromTop(TimeInterval)
-    
-    /// Flip from bottom transition.
-    case flipFromBottom(TimeInterval)
-    
-    /// Custom transition.
-    case custom(duration: TimeInterval,
-                 options: UIView.AnimationOptions,
-              animations: ((UIImageView, UIImage) -> Void)?,
-              completion: ((Bool) -> Void)?)
-    
-    var duration: TimeInterval {
-        switch self {
-        case .none:                          return 0
-        case .fade(let duration):            return duration
-            
-        case .flipFromLeft(let duration):    return duration
-        case .flipFromRight(let duration):   return duration
-        case .flipFromTop(let duration):     return duration
-        case .flipFromBottom(let duration):  return duration
-            
-        case .custom(let duration, _, _, _): return duration
-        }
-    }
-    
-    var animationOptions: UIView.AnimationOptions {
-        switch self {
-        case .none:                         return []
-        case .fade(_):                      return .transitionCrossDissolve
-            
-        case .flipFromLeft(_):              return .transitionFlipFromLeft
-        case .flipFromRight(_):             return .transitionFlipFromRight
-        case .flipFromTop(_):               return .transitionFlipFromTop
-        case .flipFromBottom(_):            return .transitionFlipFromBottom
-            
-        case .custom(_, let options, _, _): return options
-        }
-    }
-    
-    var animations: ((UIImageView, UIImage) -> Void)? {
-        switch self {
-        case .custom(_, _, let animations, _): return animations
-        default: return { $0.image = $1 }
-        }
-    }
-    
-    var completion: ((Bool) -> Void)? {
-        switch self {
-        case .custom(_, _, _, let completion): return completion
-        default: return nil
-        }
-    }
-}
-#endif

+ 0 - 263
Example/Pods/Kingfisher/Sources/ImageView+Kingfisher.swift

@@ -1,263 +0,0 @@
-//
-//  ImageView+Kingfisher.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 15/4/6.
-//
-//  Copyright (c) 2018 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.
-
-
-#if os(macOS)
-import AppKit
-#else
-import UIKit
-#endif
-
-// MARK: - Extension methods.
-/**
- *    Set image to use from web.
- */
-extension Kingfisher where Base: ImageView {
-    /**
-     Set an image with a resource, a placeholder image, options, progress handler and completion handler.
-     
-     - parameter resource:          Resource object contains information such as `cacheKey` and `downloadURL`.
-     - parameter placeholder:       A placeholder image when retrieving the image at URL.
-     - parameter options:           A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
-     - parameter progressBlock:     Called when the image downloading progress gets updated.
-     - parameter completionHandler: Called when the image retrieved and set.
-     
-     - returns: A task represents the retrieving process.
-     
-     - note: Both the `progressBlock` and `completionHandler` will be invoked in main thread.
-     The `CallbackDispatchQueue` specified in `optionsInfo` will not be used in callbacks of this method.
-     
-     If `resource` is `nil`, the `placeholder` image will be set and
-     `completionHandler` will be called with both `error` and `image` being `nil`.
-     */
-    @discardableResult
-    public func setImage(with resource: Resource?,
-                         placeholder: Placeholder? = nil,
-                         options: KingfisherOptionsInfo? = nil,
-                         progressBlock: DownloadProgressBlock? = nil,
-                         completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
-    {
-        guard let resource = resource else {
-            self.placeholder = placeholder
-            setWebURL(nil)
-            completionHandler?(nil, nil, .none, nil)
-            return .empty
-        }
-        
-        var options = KingfisherManager.shared.defaultOptions + (options ?? KingfisherEmptyOptionsInfo)
-        let noImageOrPlaceholderSet = base.image == nil && self.placeholder == nil
-        
-        if !options.keepCurrentImageWhileLoading || noImageOrPlaceholderSet { // Always set placeholder while there is no image/placehoer yet.
-            self.placeholder = placeholder
-        }
-
-        let maybeIndicator = indicator
-        maybeIndicator?.startAnimatingView()
-        
-        setWebURL(resource.downloadURL)
-
-        if base.shouldPreloadAllAnimation() {
-            options.append(.preloadAllAnimationData)
-        }
-        
-        let task = KingfisherManager.shared.retrieveImage(
-            with: resource,
-            options: options,
-            progressBlock: { receivedSize, totalSize in
-                guard resource.downloadURL == self.webURL else {
-                    return
-                }
-                if let progressBlock = progressBlock {
-                    progressBlock(receivedSize, totalSize)
-                }
-            },
-            completionHandler: {[weak base] image, error, cacheType, imageURL in
-                DispatchQueue.main.safeAsync {
-                    maybeIndicator?.stopAnimatingView()
-                    guard let strongBase = base, imageURL == self.webURL else {
-                        completionHandler?(image, error, cacheType, imageURL)
-                        return
-                    }
-                    
-                    self.setImageTask(nil)
-                    guard let image = image else {
-                        completionHandler?(nil, error, cacheType, imageURL)
-                        return
-                    }
-                    
-                    guard let transitionItem = options.lastMatchIgnoringAssociatedValue(.transition(.none)),
-                        case .transition(let transition) = transitionItem, ( options.forceTransition || cacheType == .none) else
-                    {
-                        self.placeholder = nil
-                        strongBase.image = image
-                        completionHandler?(image, error, cacheType, imageURL)
-                        return
-                    }
-                    
-                    #if !os(macOS)
-                        UIView.transition(with: strongBase, duration: 0.0, options: [],
-                                          animations: { maybeIndicator?.stopAnimatingView() },
-                                          completion: { _ in
-
-                                            self.placeholder = nil
-                                            UIView.transition(with: strongBase, duration: transition.duration,
-                                                              options: [transition.animationOptions, .allowUserInteraction],
-                                                              animations: {
-                                                                // Set image property in the animation.
-                                                                transition.animations?(strongBase, image)
-                                                              },
-                                                              completion: { finished in
-                                                                transition.completion?(finished)
-                                                                completionHandler?(image, error, cacheType, imageURL)
-                                                              })
-                                          })
-                    #endif
-                }
-            })
-        
-        setImageTask(task)
-        
-        return task
-    }
-    
-    /**
-     Cancel the image download task bounded to the image view if it is running.
-     Nothing will happen if the downloading has already finished.
-     */
-    public func cancelDownloadTask() {
-        imageTask?.cancel()
-    }
-}
-
-// MARK: - Associated Object
-private var lastURLKey: Void?
-private var indicatorKey: Void?
-private var indicatorTypeKey: Void?
-private var placeholderKey: Void?
-private var imageTaskKey: Void?
-
-extension Kingfisher where Base: ImageView {
-    /// Get the image URL binded to this image view.
-    public var webURL: URL? {
-        return objc_getAssociatedObject(base, &lastURLKey) as? URL
-    }
-    
-    fileprivate func setWebURL(_ url: URL?) {
-        objc_setAssociatedObject(base, &lastURLKey, url, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-    }
-    
-    /// Holds which indicator type is going to be used.
-    /// Default is .none, means no indicator will be shown.
-    public var indicatorType: IndicatorType {
-        get {
-            let indicator = objc_getAssociatedObject(base, &indicatorTypeKey) as? IndicatorType
-            return indicator ?? .none
-        }
-        
-        set {
-            switch newValue {
-            case .none:
-                indicator = nil
-            case .activity:
-                indicator = ActivityIndicator()
-            case .image(let data):
-                indicator = ImageIndicator(imageData: data)
-            case .custom(let anIndicator):
-                indicator = anIndicator
-            }
-            
-            objc_setAssociatedObject(base, &indicatorTypeKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-        }
-    }
-    
-    /// Holds any type that conforms to the protocol `Indicator`.
-    /// The protocol `Indicator` has a `view` property that will be shown when loading an image.
-    /// It will be `nil` if `indicatorType` is `.none`.
-    public fileprivate(set) var indicator: Indicator? {
-        get {
-            guard let box = objc_getAssociatedObject(base, &indicatorKey) as? Box<Indicator> else {
-                return nil
-            }
-            return box.value
-        }
-        
-        set {
-            // Remove previous
-            if let previousIndicator = indicator {
-                previousIndicator.view.removeFromSuperview()
-            }
-            
-            // Add new
-            if var newIndicator = newValue {
-                // Set default indicator frame if the view's frame not set.
-                if newIndicator.view.frame == .zero {
-                    newIndicator.view.frame = base.frame
-                }
-                newIndicator.viewCenter = CGPoint(x: base.bounds.midX, y: base.bounds.midY)
-                newIndicator.view.isHidden = true
-                base.addSubview(newIndicator.view)
-            }
-            
-            // Save in associated object
-            // Wrap newValue with Box to workaround an issue that Swift does not recognize
-            // and casting protocol for associate object correctly. https://github.com/onevcat/Kingfisher/issues/872
-            objc_setAssociatedObject(base, &indicatorKey, newValue.map(Box.init), .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-        }
-    }
-    
-    fileprivate var imageTask: RetrieveImageTask? {
-        return objc_getAssociatedObject(base, &imageTaskKey) as? RetrieveImageTask
-    }
-    
-    fileprivate func setImageTask(_ task: RetrieveImageTask?) {
-        objc_setAssociatedObject(base, &imageTaskKey, task, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-    }
-    
-    public fileprivate(set) var placeholder: Placeholder? {
-        get {
-            return objc_getAssociatedObject(base, &placeholderKey) as? Placeholder
-        }
-        
-        set {
-            if let previousPlaceholder = placeholder {
-                previousPlaceholder.remove(from: base)
-            }
-            
-            if let newPlaceholder = newValue {
-                newPlaceholder.add(to: base)
-            } else {
-                base.image = nil
-            }
-            
-            objc_setAssociatedObject(base, &placeholderKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-        }
-    }
-}
-
-
-@objc extension ImageView {
-    func shouldPreloadAllAnimation() -> Bool { return true }
-}

+ 0 - 203
Example/Pods/Kingfisher/Sources/Indicator.swift

@@ -1,203 +0,0 @@
-//
-//  Indicator.swift
-//  Kingfisher
-//
-//  Created by João D. Moreira on 30/08/16.
-//
-//  Copyright (c) 2018 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.
-
-#if os(macOS)
-    import AppKit
-#else
-    import UIKit
-#endif
-
-#if os(macOS)
-    public typealias IndicatorView = NSView
-#else
-    public typealias IndicatorView = UIView
-#endif
-
-public enum IndicatorType {
-    /// No indicator.
-    case none
-    /// Use system activity indicator.
-    case activity
-    /// Use an image as indicator. GIF is supported.
-    case image(imageData: Data)
-    /// Use a custom indicator, which conforms to the `Indicator` protocol.
-    case custom(indicator: Indicator)
-}
-
-// MARK: - Indicator Protocol
-public protocol Indicator {
-    func startAnimatingView()
-    func stopAnimatingView()
-
-    var viewCenter: CGPoint { get set }
-    var view: IndicatorView { get }
-}
-
-extension Indicator {
-    #if os(macOS)
-    public var viewCenter: CGPoint {
-        get {
-            let frame = view.frame
-            return CGPoint(x: frame.origin.x + frame.size.width / 2.0, y: frame.origin.y + frame.size.height / 2.0 )
-        }
-        set {
-            let frame = view.frame
-            let newFrame = CGRect(x: newValue.x - frame.size.width / 2.0,
-                                  y: newValue.y - frame.size.height / 2.0,
-                                  width: frame.size.width,
-                                  height: frame.size.height)
-            view.frame = newFrame
-        }
-    }
-    #else
-    public var viewCenter: CGPoint {
-        get {
-            return view.center
-        }
-        set {
-            view.center = newValue
-        }
-    }
-    #endif
-}
-
-// MARK: - ActivityIndicator
-// Displays a NSProgressIndicator / UIActivityIndicatorView
-final class ActivityIndicator: Indicator {
-
-    #if os(macOS)
-    private let activityIndicatorView: NSProgressIndicator
-    #else
-    private let activityIndicatorView: UIActivityIndicatorView
-    #endif
-    private var animatingCount = 0
-
-    var view: IndicatorView {
-        return activityIndicatorView
-    }
-
-    func startAnimatingView() {
-        animatingCount += 1
-        // Already animating
-        if animatingCount == 1 {
-            #if os(macOS)
-                activityIndicatorView.startAnimation(nil)
-            #else
-                activityIndicatorView.startAnimating()
-            #endif
-            activityIndicatorView.isHidden = false
-        }
-    }
-
-    func stopAnimatingView() {
-        animatingCount = max(animatingCount - 1, 0)
-        if animatingCount == 0 {
-            #if os(macOS)
-                activityIndicatorView.stopAnimation(nil)
-            #else
-                activityIndicatorView.stopAnimating()
-            #endif
-            activityIndicatorView.isHidden = true
-        }
-    }
-
-    init() {
-        #if os(macOS)
-            activityIndicatorView = NSProgressIndicator(frame: CGRect(x: 0, y: 0, width: 16, height: 16))
-            activityIndicatorView.controlSize = .small
-            activityIndicatorView.style = .spinning
-        #else
-            #if os(tvOS)
-                let indicatorStyle = UIActivityIndicatorView.Style.white
-            #else
-                let indicatorStyle = UIActivityIndicatorView.Style.gray
-            #endif
-        #if swift(>=4.2)
-            activityIndicatorView = UIActivityIndicatorView(style: indicatorStyle)
-        #else
-            activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: indicatorStyle)
-        #endif
-            activityIndicatorView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleBottomMargin, .flexibleTopMargin]
-        #endif
-    }
-}
-
-// MARK: - ImageIndicator
-// Displays an ImageView. Supports gif
-final class ImageIndicator: Indicator {
-    private let animatedImageIndicatorView: ImageView
-
-    var view: IndicatorView {
-        return animatedImageIndicatorView
-    }
-
-    init?(imageData data: Data, processor: ImageProcessor = DefaultImageProcessor.default, options: KingfisherOptionsInfo = KingfisherEmptyOptionsInfo) {
-
-        var options = options
-        // Use normal image view to show animations, so we need to preload all animation data.
-        if !options.preloadAllAnimationData {
-            options.append(.preloadAllAnimationData)
-        }
-        
-        guard let image = processor.process(item: .data(data), options: options) else {
-            return nil
-        }
-
-        animatedImageIndicatorView = ImageView()
-        animatedImageIndicatorView.image = image
-        animatedImageIndicatorView.frame = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
-        
-        #if os(macOS)
-            // Need for gif to animate on macOS
-            self.animatedImageIndicatorView.imageScaling = .scaleNone
-            self.animatedImageIndicatorView.canDrawSubviewsIntoLayer = true
-        #else
-            animatedImageIndicatorView.contentMode = .center
-            animatedImageIndicatorView.autoresizingMask = [.flexibleLeftMargin,
-                                                           .flexibleRightMargin,
-                                                           .flexibleBottomMargin,
-                                                           .flexibleTopMargin]
-        #endif
-    }
-
-    func startAnimatingView() {
-        #if os(macOS)
-            animatedImageIndicatorView.animates = true
-        #else
-            animatedImageIndicatorView.startAnimating()
-        #endif
-        animatedImageIndicatorView.isHidden = false
-    }
-
-    func stopAnimatingView() {
-        #if os(macOS)
-            animatedImageIndicatorView.animates = false
-        #else
-            animatedImageIndicatorView.stopAnimating()
-        #endif
-        animatedImageIndicatorView.isHidden = true
-    }
-}

+ 0 - 37
Example/Pods/Kingfisher/Sources/Kingfisher.h

@@ -1,37 +0,0 @@
-//
-//  Kingfisher.h
-//  Kingfisher
-//
-//  Created by Wei Wang on 15/4/6.
-//
-//  Copyright (c) 2018 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.
-
-#import <Foundation/Foundation.h>
-
-//! Project version number for Kingfisher.
-FOUNDATION_EXPORT double KingfisherVersionNumber;
-
-//! Project version string for Kingfisher.
-FOUNDATION_EXPORT const unsigned char KingfisherVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import <Kingfisher/PublicHeader.h>
-
-

+ 0 - 77
Example/Pods/Kingfisher/Sources/Kingfisher.swift

@@ -1,77 +0,0 @@
-//
-//  Kingfisher.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 16/9/14.
-//
-//  Copyright (c) 2018 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.
-
-import Foundation
-import ImageIO
-
-#if os(macOS)
-    import AppKit
-    public typealias Image = NSImage
-    public typealias View = NSView
-    public typealias Color = NSColor
-    public typealias ImageView = NSImageView
-    public typealias Button = NSButton
-#else
-    import UIKit
-    public typealias Image = UIImage
-    public typealias Color = UIColor
-    #if !os(watchOS)
-    public typealias ImageView = UIImageView
-    public typealias View = UIView
-    public typealias Button = UIButton
-    #else
-    import WatchKit
-    #endif
-#endif
-
-public final class Kingfisher<Base> {
-    public let base: Base
-    public init(_ base: Base) {
-        self.base = base
-    }
-}
-
-/**
- A type that has Kingfisher extensions.
- */
-public protocol KingfisherCompatible {
-    associatedtype CompatibleType
-    var kf: CompatibleType { get }
-}
-
-public extension KingfisherCompatible {
-    public var kf: Kingfisher<Self> {
-        return Kingfisher(self)
-    }
-}
-
-extension Image: KingfisherCompatible { }
-#if !os(watchOS)
-extension ImageView: KingfisherCompatible { }
-extension Button: KingfisherCompatible { }
-#else
-extension WKInterfaceImage: KingfisherCompatible { }
-#endif

+ 0 - 297
Example/Pods/Kingfisher/Sources/KingfisherManager.swift

@@ -1,297 +0,0 @@
-//
-//  KingfisherManager.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 15/4/6.
-//
-//  Copyright (c) 2018 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.
-
-#if os(macOS)
-import AppKit
-#else
-import UIKit
-#endif
-
-public typealias DownloadProgressBlock = ((_ receivedSize: Int64, _ totalSize: Int64) -> Void)
-public typealias CompletionHandler = ((_ image: Image?, _ error: NSError?, _ cacheType: CacheType, _ imageURL: URL?) -> Void)
-
-/// RetrieveImageTask represents a task of image retrieving process.
-/// It contains an async task of getting image from disk and from network.
-public final class RetrieveImageTask {
-    
-    public static let empty = RetrieveImageTask()
-    
-    // If task is canceled before the download task started (which means the `downloadTask` is nil),
-    // the download task should not begin.
-    var cancelledBeforeDownloadStarting: Bool = false
-    
-    /// The network retrieve task in this image task.
-    public var downloadTask: RetrieveImageDownloadTask?
-    
-    /**
-    Cancel current task. If this task is already done, do nothing.
-    */
-    public func cancel() {
-        if let downloadTask = downloadTask {
-            downloadTask.cancel()
-        } else {
-            cancelledBeforeDownloadStarting = true
-        }
-    }
-}
-
-/// Error domain of Kingfisher
-public let KingfisherErrorDomain = "com.onevcat.Kingfisher.Error"
-
-/// Main manager class of Kingfisher. It connects Kingfisher downloader and cache.
-/// You can use this class to retrieve an image via a specified URL from web or cache.
-public class KingfisherManager {
-    
-    /// Shared manager used by the extensions across Kingfisher.
-    public static let shared = KingfisherManager()
-    
-    /// Cache used by this manager
-    public var cache: ImageCache
-    
-    /// Downloader used by this manager
-    public var downloader: ImageDownloader
-    
-    /// Default options used by the manager. This option will be used in 
-    /// Kingfisher manager related methods, including all image view and 
-    /// button extension methods. You can also passing the options per image by 
-    /// sending an `options` parameter to Kingfisher's APIs, the per image option 
-    /// will overwrite the default ones if exist.
-    ///
-    /// - Note: This option will not be applied to independent using of `ImageDownloader` or `ImageCache`.
-    public var defaultOptions = KingfisherEmptyOptionsInfo
-    
-    var currentDefaultOptions: KingfisherOptionsInfo {
-        return [.downloader(downloader), .targetCache(cache)] + defaultOptions
-    }
-
-    fileprivate let processQueue: DispatchQueue
-    
-    convenience init() {
-        self.init(downloader: .default, cache: .default)
-    }
-    
-    init(downloader: ImageDownloader, cache: ImageCache) {
-        self.downloader = downloader
-        self.cache = cache
-
-        let processQueueName = "com.onevcat.Kingfisher.KingfisherManager.processQueue.\(UUID().uuidString)"
-        processQueue = DispatchQueue(label: processQueueName, attributes: .concurrent)
-    }
-    
-    /**
-    Get an image with resource.
-    If KingfisherOptions.None is used as `options`, Kingfisher will seek the image in memory and disk first.
-    If not found, it will download the image at `resource.downloadURL` and cache it with `resource.cacheKey`.
-    These default behaviors could be adjusted by passing different options. See `KingfisherOptions` for more.
-    
-    - parameter resource:          Resource object contains information such as `cacheKey` and `downloadURL`.
-    - parameter options:           A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
-    - parameter progressBlock:     Called every time downloaded data changed. This could be used as a progress UI.
-    - parameter completionHandler: Called when the whole retrieving process finished.
-    
-    - returns: A `RetrieveImageTask` task object. You can use this object to cancel the task.
-    */
-    @discardableResult
-    public func retrieveImage(with resource: Resource,
-        options: KingfisherOptionsInfo?,
-        progressBlock: DownloadProgressBlock?,
-        completionHandler: CompletionHandler?) -> RetrieveImageTask
-    {
-        let task = RetrieveImageTask()
-        let options = currentDefaultOptions + (options ?? KingfisherEmptyOptionsInfo)
-        if options.forceRefresh {
-            _ = downloadAndCacheImage(
-                with: resource.downloadURL,
-                forKey: resource.cacheKey,
-                retrieveImageTask: task,
-                progressBlock: progressBlock,
-                completionHandler: completionHandler,
-                options: options)
-        } else {
-            tryToRetrieveImageFromCache(
-                forKey: resource.cacheKey,
-                with: resource.downloadURL,
-                retrieveImageTask: task,
-                progressBlock: progressBlock,
-                completionHandler: completionHandler,
-                options: options)
-        }
-        
-        return task
-    }
-
-    @discardableResult
-    func downloadAndCacheImage(with url: URL,
-                             forKey key: String,
-                      retrieveImageTask: RetrieveImageTask,
-                          progressBlock: DownloadProgressBlock?,
-                      completionHandler: CompletionHandler?,
-                                options: KingfisherOptionsInfo) -> RetrieveImageDownloadTask?
-    {
-        let downloader = options.downloader ?? self.downloader
-        let processQueue = self.processQueue
-        return downloader.downloadImage(with: url, retrieveImageTask: retrieveImageTask, options: options,
-            progressBlock: { receivedSize, totalSize in
-                progressBlock?(receivedSize, totalSize)
-            },
-            completionHandler: { image, error, imageURL, originalData in
-
-                let targetCache = options.targetCache ?? self.cache
-                if let error = error, error.code == KingfisherError.notModified.rawValue {
-                    // Not modified. Try to find the image from cache.
-                    // (The image should be in cache. It should be guaranteed by the framework users.)
-                    targetCache.retrieveImage(forKey: key, options: options, completionHandler: { (cacheImage, cacheType) -> Void in
-                        completionHandler?(cacheImage, nil, cacheType, url)
-                    })
-                    return
-                }
-                
-                if let image = image, let originalData = originalData {
-                    targetCache.store(image,
-                                      original: originalData,
-                                      forKey: key,
-                                      processorIdentifier:options.processor.identifier,
-                                      cacheSerializer: options.cacheSerializer,
-                                      toDisk: !options.cacheMemoryOnly,
-                                      completionHandler: {
-                                        guard options.waitForCache else { return }
-                                        
-                                        let cacheType = targetCache.imageCachedType(forKey: key, processorIdentifier: options.processor.identifier)
-                                        completionHandler?(image, nil, cacheType, url)
-                    })
-                    
-                    if options.cacheOriginalImage && options.processor != DefaultImageProcessor.default {
-                        let originalCache = options.originalCache ?? targetCache
-                        let defaultProcessor = DefaultImageProcessor.default
-                        processQueue.async {
-                            if let originalImage = defaultProcessor.process(item: .data(originalData), options: options) {
-                                originalCache.store(originalImage,
-                                                    original: originalData,
-                                                    forKey: key,
-                                                    processorIdentifier: defaultProcessor.identifier,
-                                                    cacheSerializer: options.cacheSerializer,
-                                                    toDisk: !options.cacheMemoryOnly,
-                                                    completionHandler: nil)
-                            }
-                        }
-                    }
-                }
-
-                if options.waitForCache == false || image == nil {
-                    completionHandler?(image, error, .none, url)
-                }
-            })
-    }
-    
-    func tryToRetrieveImageFromCache(forKey key: String,
-                                       with url: URL,
-                              retrieveImageTask: RetrieveImageTask,
-                                  progressBlock: DownloadProgressBlock?,
-                              completionHandler: CompletionHandler?,
-                                        options: KingfisherOptionsInfo)
-    {
-
-        let diskTaskCompletionHandler: CompletionHandler = { (image, error, cacheType, imageURL) -> Void in
-            completionHandler?(image, error, cacheType, imageURL)
-        }
-        
-        func handleNoCache() {
-            if options.onlyFromCache {
-                let error = NSError(domain: KingfisherErrorDomain, code: KingfisherError.notCached.rawValue, userInfo: nil)
-                diskTaskCompletionHandler(nil, error, .none, url)
-                return
-            }
-            self.downloadAndCacheImage(
-                with: url,
-                forKey: key,
-                retrieveImageTask: retrieveImageTask,
-                progressBlock: progressBlock,
-                completionHandler: diskTaskCompletionHandler,
-                options: options)
-            
-        }
-        
-        let targetCache = options.targetCache ?? self.cache
-        let processQueue = self.processQueue
-        // First, try to get the exactly image from cache
-        targetCache.retrieveImage(forKey: key, options: options) { image, cacheType in
-            // If found, we could finish now.
-            if image != nil {
-                diskTaskCompletionHandler(image, nil, cacheType, url)
-                return
-            }
-            
-            // If not found, and we are using a default processor, download it!
-            let processor = options.processor
-            guard processor != DefaultImageProcessor.default else {
-                handleNoCache()
-                return
-            }
-            
-            // If processor is not the default one, we have a chance to check whether
-            // the original image is already in cache.
-            let originalCache = options.originalCache ?? targetCache
-            let optionsWithoutProcessor = options.removeAllMatchesIgnoringAssociatedValue(.processor(processor))
-            originalCache.retrieveImage(forKey: key, options: optionsWithoutProcessor) { image, cacheType in
-                // If we found the original image, there is no need to download it again.
-                // We could just apply processor to it now.
-                guard let image = image else {
-                    handleNoCache()
-                    return
-                }
-
-                processQueue.async {
-                    guard let processedImage = processor.process(item: .image(image), options: options) else {
-                        options.callbackDispatchQueue.safeAsync {
-                            diskTaskCompletionHandler(nil, nil, .none, url)
-                        }
-                        return
-                    }
-                    targetCache.store(processedImage,
-                                      original: nil,
-                                      forKey: key,
-                                      processorIdentifier:options.processor.identifier,
-                                      cacheSerializer: options.cacheSerializer,
-                                      toDisk: !options.cacheMemoryOnly,
-                                      completionHandler: {
-                                        guard options.waitForCache else { return }
-
-                                        let cacheType = targetCache.imageCachedType(forKey: key, processorIdentifier: options.processor.identifier)
-                                        options.callbackDispatchQueue.safeAsync {
-                                            diskTaskCompletionHandler(processedImage, nil, cacheType, url)
-                                        }
-                    })
-
-                    if options.waitForCache == false {
-                        options.callbackDispatchQueue.safeAsync {
-                            diskTaskCompletionHandler(processedImage, nil, .none, url)
-                        }
-                    }
-                }
-            }
-        }
-    }
-}

+ 0 - 364
Example/Pods/Kingfisher/Sources/KingfisherOptionsInfo.swift

@@ -1,364 +0,0 @@
-//
-//  KingfisherOptionsInfo.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 15/4/23.
-//
-//  Copyright (c) 2018 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.
-
-#if os(macOS)
-import AppKit
-#else
-import UIKit
-#endif
-    
-
-/**
-*	KingfisherOptionsInfo is a typealias for [KingfisherOptionsInfoItem]. You can use the enum of option item with value to control some behaviors of Kingfisher.
-*/
-public typealias KingfisherOptionsInfo = [KingfisherOptionsInfoItem]
-let KingfisherEmptyOptionsInfo = [KingfisherOptionsInfoItem]()
-
-/**
-Items could be added into KingfisherOptionsInfo.
-*/
-public enum KingfisherOptionsInfoItem {
-    /// The associated value of this member should be an ImageCache object. Kingfisher will use the specified
-    /// cache object when handling related operations, including trying to retrieve the cached images and store
-    /// the downloaded image to it.
-    case targetCache(ImageCache)
-    
-    /// Cache for storing and retrieving original image.
-    /// Preferred prior to targetCache for storing and retrieving original images if specified.
-    /// Only used if a non-default image processor is involved.
-    case originalCache(ImageCache)
-    
-    /// The associated value of this member should be an ImageDownloader object. Kingfisher will use this
-    /// downloader to download the images.
-    case downloader(ImageDownloader)
-    
-    /// Member for animation transition when using UIImageView. Kingfisher will use the `ImageTransition` of
-    /// this enum to animate the image in if it is downloaded from web. The transition will not happen when the
-    /// image is retrieved from either memory or disk cache by default. If you need to do the transition even when
-    /// the image being retrieved from cache, set `ForceTransition` as well.
-    case transition(ImageTransition)
-    
-    /// Associated `Float` value will be set as the priority of image download task. The value for it should be
-    /// between 0.0~1.0. If this option not set, the default value (`NSURLSessionTaskPriorityDefault`) will be used.
-    case downloadPriority(Float)
-    
-    /// If set, `Kingfisher` will ignore the cache and try to fire a download task for the resource.
-    case forceRefresh
-
-    /// If set, `Kingfisher` will try to retrieve the image from memory cache first. If the image is not in memory
-    /// cache, then it will ignore the disk cache but download the image again from network. This is useful when
-    /// you want to display a changeable image behind the same url, while avoiding download it again and again.
-    case fromMemoryCacheOrRefresh
-    
-    /// If set, setting the image to an image view will happen with transition even when retrieved from cache.
-    /// See `Transition` option for more.
-    case forceTransition
-    
-    ///  If set, `Kingfisher` will only cache the value in memory but not in disk.
-    case cacheMemoryOnly
-    
-    ///  If set, `Kingfisher` will wait for caching operation to be completed before calling the completion block.
-    case waitForCache
-    
-    /// If set, `Kingfisher` will only try to retrieve the image from cache not from network.
-    case onlyFromCache
-    
-    /// Decode the image in background thread before using.
-    case backgroundDecode
-    
-    /// The associated value of this member will be used as the target queue of dispatch callbacks when
-    /// retrieving images from cache. If not set, `Kingfisher` will use main queue for callbacks.
-    case callbackDispatchQueue(DispatchQueue?)
-    
-    /// The associated value of this member will be used as the scale factor when converting retrieved data to an image.
-    /// It is the image scale, instead of your screen scale. You may need to specify the correct scale when you dealing 
-    /// with 2x or 3x retina images.
-    case scaleFactor(CGFloat)
-
-    /// Whether all the animated image data should be preloaded. Default it false, which means following frames will be
-    /// loaded on need. If true, all the animated image data will be loaded and decoded into memory. This option is mainly
-    /// used for back compatibility internally. You should not set it directly. `AnimatedImageView` will not preload
-    /// all data, while a normal image view (`UIImageView` or `NSImageView`) will load all data. Choose to use
-    /// corresponding image view type instead of setting this option.
-    case preloadAllAnimationData
-    
-    /// The `ImageDownloadRequestModifier` contained will be used to change the request before it being sent.
-    /// This is the last chance you can modify the request. You can modify the request for some customizing purpose,
-    /// such as adding auth token to the header, do basic HTTP auth or something like url mapping. The original request
-    /// will be sent without any modification by default.
-    case requestModifier(ImageDownloadRequestModifier)
-    
-    /// Processor for processing when the downloading finishes, a processor will convert the downloaded data to an image
-    /// and/or apply some filter on it. If a cache is connected to the downloader (it happens when you are using
-    /// KingfisherManager or the image extension methods), the converted image will also be sent to cache as well as the
-    /// image view. `DefaultImageProcessor.default` will be used by default.
-    case processor(ImageProcessor)
-    
-    /// Supply an `CacheSerializer` to convert some data to an image object for
-    /// retrieving from disk cache or vice versa for storing to disk cache.
-    /// `DefaultCacheSerializer.default` will be used by default.
-    case cacheSerializer(CacheSerializer)
-
-    /// Modifier for modifying an image right before it is used.
-    /// If the image was fetched directly from the downloader, the modifier will
-    /// run directly after the processor.
-    /// If the image is being fetched from a cache, the modifier will run after
-    /// the cacheSerializer.
-    /// Use `ImageModifier` when you need to set properties on a concrete type
-    /// of `Image`, such as a `UIImage`, that do not persist when caching the image.
-    case imageModifier(ImageModifier)
-    
-    /// Keep the existing image while setting another image to an image view.
-    /// By setting this option, the placeholder image parameter of imageview extension method
-    /// will be ignored and the current image will be kept while loading or downloading the new image.
-    case keepCurrentImageWhileLoading
-    
-    /// If set, Kingfisher will only load the first frame from a animated image data file as a single image.
-    /// Loading a lot of animated images may take too much memory. It will be useful when you want to display a
-    /// static preview of the first frame from a animated image.
-    /// This option will be ignored if the target image is not animated image data.
-    case onlyLoadFirstFrame
-    
-    /// If set and an `ImageProcessor` is used, Kingfisher will try to cache both 
-    /// the final result and original image. Kingfisher will have a chance to use 
-    /// the original image when another processor is applied to the same resource,
-    /// instead of downloading it again.
-    case cacheOriginalImage
-}
-
-precedencegroup ItemComparisonPrecedence {
-    associativity: none
-    higherThan: LogicalConjunctionPrecedence
-}
-
-infix operator <== : ItemComparisonPrecedence
-
-// This operator returns true if two `KingfisherOptionsInfoItem` enum is the same, without considering the associated values.
-func <== (lhs: KingfisherOptionsInfoItem, rhs: KingfisherOptionsInfoItem) -> Bool {
-    switch (lhs, rhs) {
-    case (.targetCache(_), .targetCache(_)): return true
-    case (.originalCache(_), .originalCache(_)): return true
-    case (.downloader(_), .downloader(_)): return true
-    case (.transition(_), .transition(_)): return true
-    case (.downloadPriority(_), .downloadPriority(_)): return true
-    case (.forceRefresh, .forceRefresh): return true
-    case (.fromMemoryCacheOrRefresh, .fromMemoryCacheOrRefresh): return true
-    case (.forceTransition, .forceTransition): return true
-    case (.cacheMemoryOnly, .cacheMemoryOnly): return true
-    case (.waitForCache, .waitForCache): return true
-    case (.onlyFromCache, .onlyFromCache): return true
-    case (.backgroundDecode, .backgroundDecode): return true
-    case (.callbackDispatchQueue(_), .callbackDispatchQueue(_)): return true
-    case (.scaleFactor(_), .scaleFactor(_)): return true
-    case (.preloadAllAnimationData, .preloadAllAnimationData): return true
-    case (.requestModifier(_), .requestModifier(_)): return true
-    case (.processor(_), .processor(_)): return true
-    case (.cacheSerializer(_), .cacheSerializer(_)): return true
-    case (.imageModifier(_), .imageModifier(_)): return true
-    case (.keepCurrentImageWhileLoading, .keepCurrentImageWhileLoading): return true
-    case (.onlyLoadFirstFrame, .onlyLoadFirstFrame): return true
-    case (.cacheOriginalImage, .cacheOriginalImage): return true
-    default: return false
-    }
-}
-
-
-extension Collection where Iterator.Element == KingfisherOptionsInfoItem {
-    func lastMatchIgnoringAssociatedValue(_ target: Iterator.Element) -> Iterator.Element? {
-        return reversed().first { $0 <== target }
-    }
-    
-    func removeAllMatchesIgnoringAssociatedValue(_ target: Iterator.Element) -> [Iterator.Element] {
-        return filter { !($0 <== target) }
-    }
-}
-
-public extension Collection where Iterator.Element == KingfisherOptionsInfoItem {
-    /// The target `ImageCache` which is used.
-    public var targetCache: ImageCache? {
-        if let item = lastMatchIgnoringAssociatedValue(.targetCache(.default)),
-            case .targetCache(let cache) = item
-        {
-            return cache
-        }
-        return nil
-    }
-    
-    /// The original `ImageCache` which is used.
-    public var originalCache: ImageCache? {
-        if let item = lastMatchIgnoringAssociatedValue(.originalCache(.default)),
-            case .originalCache(let cache) = item
-        {
-            return cache
-        }
-        return targetCache
-    }
-    
-    /// The `ImageDownloader` which is specified.
-    public var downloader: ImageDownloader? {
-        if let item = lastMatchIgnoringAssociatedValue(.downloader(.default)),
-            case .downloader(let downloader) = item
-        {
-            return downloader
-        }
-        return nil
-    }
-    
-    /// Member for animation transition when using UIImageView.
-    public var transition: ImageTransition {
-        if let item = lastMatchIgnoringAssociatedValue(.transition(.none)),
-            case .transition(let transition) = item
-        {
-            return transition
-        }
-        return ImageTransition.none
-    }
-    
-    /// A `Float` value set as the priority of image download task. The value for it should be
-    /// between 0.0~1.0.
-    public var downloadPriority: Float {
-        if let item = lastMatchIgnoringAssociatedValue(.downloadPriority(0)),
-            case .downloadPriority(let priority) = item
-        {
-            return priority
-        }
-        return URLSessionTask.defaultPriority
-    }
-    
-    /// Whether an image will be always downloaded again or not.
-    public var forceRefresh: Bool {
-        return contains{ $0 <== .forceRefresh }
-    }
-
-    /// Whether an image should be got only from memory cache or download.
-    public var fromMemoryCacheOrRefresh: Bool {
-        return contains{ $0 <== .fromMemoryCacheOrRefresh }
-    }
-    
-    /// Whether the transition should always happen or not.
-    public var forceTransition: Bool {
-        return contains{ $0 <== .forceTransition }
-    }
-    
-    /// Whether cache the image only in memory or not.
-    public var cacheMemoryOnly: Bool {
-        return contains{ $0 <== .cacheMemoryOnly }
-    }
-    
-    /// Whether the caching operation will be waited or not.
-    public var waitForCache: Bool {
-        return contains{ $0 <== .waitForCache }
-    }
-    
-    /// Whether only load the images from cache or not.
-    public var onlyFromCache: Bool {
-        return contains{ $0 <== .onlyFromCache }
-    }
-    
-    /// Whether the image should be decoded in background or not.
-    public var backgroundDecode: Bool {
-        return contains{ $0 <== .backgroundDecode }
-    }
-
-    /// Whether the image data should be all loaded at once if it is an animated image.
-    public var preloadAllAnimationData: Bool {
-        return contains { $0 <== .preloadAllAnimationData }
-    }
-    
-    /// The queue of callbacks should happen from Kingfisher.
-    public var callbackDispatchQueue: DispatchQueue {
-        if let item = lastMatchIgnoringAssociatedValue(.callbackDispatchQueue(nil)),
-            case .callbackDispatchQueue(let queue) = item
-        {
-            return queue ?? DispatchQueue.main
-        }
-        return DispatchQueue.main
-    }
-    
-    /// The scale factor which should be used for the image.
-    public var scaleFactor: CGFloat {
-        if let item = lastMatchIgnoringAssociatedValue(.scaleFactor(0)),
-            case .scaleFactor(let scale) = item
-        {
-            return scale
-        }
-        return 1.0
-    }
-    
-    /// The `ImageDownloadRequestModifier` will be used before sending a download request.
-    public var modifier: ImageDownloadRequestModifier {
-        if let item = lastMatchIgnoringAssociatedValue(.requestModifier(NoModifier.default)),
-            case .requestModifier(let modifier) = item
-        {
-            return modifier
-        }
-        return NoModifier.default
-    }
-    
-    /// `ImageProcessor` for processing when the downloading finishes.
-    public var processor: ImageProcessor {
-        if let item = lastMatchIgnoringAssociatedValue(.processor(DefaultImageProcessor.default)),
-            case .processor(let processor) = item
-        {
-            return processor
-        }
-        return DefaultImageProcessor.default
-    }
-
-    /// `ImageModifier` for modifying right before the image is displayed.
-    public var imageModifier: ImageModifier {
-        if let item = lastMatchIgnoringAssociatedValue(.imageModifier(DefaultImageModifier.default)),
-            case .imageModifier(let imageModifier) = item
-        {
-            return imageModifier
-        }
-        return DefaultImageModifier.default
-    }
-    
-    /// `CacheSerializer` to convert image to data for storing in cache.
-    public var cacheSerializer: CacheSerializer {
-        if let item = lastMatchIgnoringAssociatedValue(.cacheSerializer(DefaultCacheSerializer.default)),
-            case .cacheSerializer(let cacheSerializer) = item
-        {
-            return cacheSerializer
-        }
-        return DefaultCacheSerializer.default
-    }
-    
-    /// Keep the existing image while setting another image to an image view. 
-    /// Or the placeholder will be used while downloading.
-    public var keepCurrentImageWhileLoading: Bool {
-        return contains { $0 <== .keepCurrentImageWhileLoading }
-    }
-    
-    public var onlyLoadFirstFrame: Bool {
-        return contains { $0 <== .onlyLoadFirstFrame }
-    }
-    
-    public var cacheOriginalImage: Bool {
-        return contains { $0 <== .cacheOriginalImage }
-    }
-}

+ 0 - 82
Example/Pods/Kingfisher/Sources/Placeholder.swift

@@ -1,82 +0,0 @@
-//
-//  Placeholder.swift
-//  Kingfisher
-//
-//  Created by Tieme van Veen on 28/08/2017.
-//
-//  Copyright (c) 2018 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.
-
-#if os(macOS)
-    import AppKit
-#else
-    import UIKit
-#endif
-
-
-/// Represent a placeholder type which could be set while loading as well as
-/// loading finished without getting an image.
-public protocol Placeholder {
-    
-    /// How the placeholder should be added to a given image view.
-    func add(to imageView: ImageView)
-    
-    /// How the placeholder should be removed from a given image view.
-    func remove(from imageView: ImageView)
-}
-
-/// Default implementation of an image placeholder. The image will be set or 
-/// reset directly for `image` property of the image view.
-extension Placeholder where Self: Image {
-    
-    /// How the placeholder should be added to a given image view.
-    public func add(to imageView: ImageView) { imageView.image = self }
-    
-    /// How the placeholder should be removed from a given image view.
-    public func remove(from imageView: ImageView) { imageView.image = nil }
-}
-
-extension Image: Placeholder {}
-
-/// Default implementation of an arbitrary view as placeholder. The view will be 
-/// added as a subview when adding and be removed from its super view when removing.
-///
-/// To use your customize View type as placeholder, simply let it conforming to 
-/// `Placeholder` by `extension MyView: Placeholder {}`.
-extension Placeholder where Self: View {
-    
-    /// How the placeholder should be added to a given image view.
-    public func add(to imageView: ImageView) {
-        imageView.addSubview(self)
-
-        self.translatesAutoresizingMaskIntoConstraints = false
-        NSLayoutConstraint.activate([
-            NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: imageView, attribute: .centerX, multiplier: 1, constant: 0),
-            NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: imageView, attribute: .centerY, multiplier: 1, constant: 0),
-            NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: imageView, attribute: .height, multiplier: 1, constant: 0),
-            NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: imageView, attribute: .width, multiplier: 1, constant: 0)
-            ])
-    }
-
-    /// How the placeholder should be removed from a given image view.
-    public func remove(from imageView: ImageView) {
-        self.removeFromSuperview()
-    }
-}

+ 0 - 53
Example/Pods/Kingfisher/Sources/RequestModifier.swift

@@ -1,53 +0,0 @@
-//
-//  RequestModifier.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 2016/09/05.
-//
-//  Copyright (c) 2018 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.
-
-import Foundation
-
-/// Request modifier of image downloader.
-public protocol ImageDownloadRequestModifier {
-    func modified(for request: URLRequest) -> URLRequest?
-}
-
-struct NoModifier: ImageDownloadRequestModifier {
-    static let `default` = NoModifier()
-    private init() {}
-    func modified(for request: URLRequest) -> URLRequest? {
-        return request
-    }
-}
-
-public struct AnyModifier: ImageDownloadRequestModifier {
-    
-    let block: (URLRequest) -> URLRequest?
-    
-    public func modified(for request: URLRequest) -> URLRequest? {
-        return block(request)
-    }
-    
-    public init(modify: @escaping (URLRequest) -> URLRequest? ) {
-        block = modify
-    }
-}

+ 0 - 74
Example/Pods/Kingfisher/Sources/Resource.swift

@@ -1,74 +0,0 @@
-//
-//  Resource.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 15/4/6.
-//
-//  Copyright (c) 2018 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.
-
-import Foundation
-
-
-/// `Resource` protocol defines how to download and cache a resource from network.
-public protocol Resource {
-    /// The key used in cache.
-    var cacheKey: String { get }
-    
-    /// The target image URL.
-    var downloadURL: URL { get }
-}
-
-/**
- ImageResource is a simple combination of `downloadURL` and `cacheKey`.
- 
- When passed to image view set methods, Kingfisher will try to download the target 
- image from the `downloadURL`, and then store it with the `cacheKey` as the key in cache.
- */
-public struct ImageResource: Resource {
-    /// The key used in cache.
-    public let cacheKey: String
-    
-    /// The target image URL.
-    public let downloadURL: URL
-    
-    /**
-     Create a resource.
-     
-     - parameter downloadURL: The target image URL.
-     - parameter cacheKey:    The cache key. If `nil`, Kingfisher will use the `absoluteString` of `downloadURL` as the key.
-     
-     - returns: A resource.
-     */
-    public init(downloadURL: URL, cacheKey: String? = nil) {
-        self.downloadURL = downloadURL
-        self.cacheKey = cacheKey ?? downloadURL.absoluteString
-    }
-}
-
-/**
- URL conforms to `Resource` in Kingfisher.
- The `absoluteString` of this URL is used as `cacheKey`. And the URL itself will be used as `downloadURL`.
- If you need customize the url and/or cache key, use `ImageResource` instead.
- */
-extension URL: Resource {
-    public var cacheKey: String { return absoluteString }
-    public var downloadURL: URL { return self }
-}

+ 0 - 285
Example/Pods/Kingfisher/Sources/String+MD5.swift

@@ -1,285 +0,0 @@
-//
-//  String+MD5.swift
-//  Kingfisher
-//
-// To date, adding CommonCrypto to a Swift framework is problematic. See:
-// http://stackoverflow.com/questions/25248598/importing-commoncrypto-in-a-swift-framework
-// We're using a subset and modified version of CryptoSwift as an alternative.
-// The following is an altered source version that only includes MD5. The original software can be found at:
-// https://github.com/krzyzanowskim/CryptoSwift
-// This is the original copyright notice:
-
-/*
-Copyright (C) 2014 Marcin Krzyżanowski <marcin.krzyzanowski@gmail.com>
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
-- The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
-- Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-- This notice may not be removed or altered from any source or binary distribution.
-*/
-
-import Foundation
-
-extension String: KingfisherCompatible { }
-
-extension Kingfisher where Base == String {
-    public var md5: String {
-        if let data = base.data(using: .utf8, allowLossyConversion: true) {
-
-            let message = data.withUnsafeBytes { bytes -> [UInt8] in
-                return Array(UnsafeBufferPointer(start: bytes, count: data.count))
-            }
-
-            let MD5Calculator = MD5(message)
-            let MD5Data = MD5Calculator.calculate()
-
-            var MD5String = String()
-            for c in MD5Data {
-                MD5String += String(format: "%02x", c)
-            }
-            return MD5String
-
-        } else {
-            return base
-        }
-    }
-}
-
-
-/** array of bytes, little-endian representation */
-func arrayOfBytes<T>(_ value: T, length: Int? = nil) -> [UInt8] {
-    let totalBytes = length ?? (MemoryLayout<T>.size * 8)
-    
-    let valuePointer = UnsafeMutablePointer<T>.allocate(capacity: 1)
-    valuePointer.pointee = value
-
-    let bytes = valuePointer.withMemoryRebound(to: UInt8.self, capacity: totalBytes) { (bytesPointer) -> [UInt8] in
-        var bytes = [UInt8](repeating: 0, count: totalBytes)
-        for j in 0..<min(MemoryLayout<T>.size, totalBytes) {
-            bytes[totalBytes - 1 - j] = (bytesPointer + j).pointee
-        }
-        return bytes
-    }
-
-    #if swift(>=4.1)
-    valuePointer.deinitialize(count: 1)
-    valuePointer.deallocate()
-    #else
-    valuePointer.deinitialize()
-    valuePointer.deallocate(capacity: 1)
-    #endif
-    
-    return bytes
-}
-
-extension Int {
-    /** Array of bytes with optional padding (little-endian) */
-    func bytes(_ totalBytes: Int = MemoryLayout<Int>.size) -> [UInt8] {
-        return arrayOfBytes(self, length: totalBytes)
-    }
-    
-}
-
-extension NSMutableData {
-    
-    /** Convenient way to append bytes */
-    func appendBytes(_ arrayOfBytes: [UInt8]) {
-        append(arrayOfBytes, length: arrayOfBytes.count)
-    }
-    
-}
-
-protocol HashProtocol {
-    var message: Array<UInt8> { get }
-    
-    /** Common part for hash calculation. Prepare header data. */
-    func prepare(_ len: Int) -> Array<UInt8>
-}
-
-extension HashProtocol {
-    
-    func prepare(_ len: Int) -> Array<UInt8> {
-        var tmpMessage = message
-        
-        // Step 1. Append Padding Bits
-        tmpMessage.append(0x80) // append one bit (UInt8 with one bit) to message
-        
-        // append "0" bit until message length in bits ≡ 448 (mod 512)
-        var msgLength = tmpMessage.count
-        var counter = 0
-        
-        while msgLength % len != (len - 8) {
-            counter += 1
-            msgLength += 1
-        }
-        
-        tmpMessage += Array<UInt8>(repeating: 0, count: counter)
-        return tmpMessage
-    }
-}
-
-func toUInt32Array(_ slice: ArraySlice<UInt8>) -> Array<UInt32> {
-    var result = Array<UInt32>()
-    result.reserveCapacity(16)
-    
-    for idx in stride(from: slice.startIndex, to: slice.endIndex, by: MemoryLayout<UInt32>.size) {
-        let d0 = UInt32(slice[idx.advanced(by: 3)]) << 24
-        let d1 = UInt32(slice[idx.advanced(by: 2)]) << 16
-        let d2 = UInt32(slice[idx.advanced(by: 1)]) << 8
-        let d3 = UInt32(slice[idx])
-        let val: UInt32 = d0 | d1 | d2 | d3
-                         
-        result.append(val)
-    }
-    return result
-}
-
-struct BytesIterator: IteratorProtocol {
-    
-    let chunkSize: Int
-    let data: [UInt8]
-    
-    init(chunkSize: Int, data: [UInt8]) {
-        self.chunkSize = chunkSize
-        self.data = data
-    }
-    
-    var offset = 0
-    
-    mutating func next() -> ArraySlice<UInt8>? {
-        let end = min(chunkSize, data.count - offset)
-        let result = data[offset..<offset + end]
-        offset += result.count
-        return result.count > 0 ? result : nil
-    }
-}
-
-struct BytesSequence: Sequence {
-    let chunkSize: Int
-    let data: [UInt8]
-    
-    func makeIterator() -> BytesIterator {
-        return BytesIterator(chunkSize: chunkSize, data: data)
-    }
-}
-
-func rotateLeft(_ value: UInt32, bits: UInt32) -> UInt32 {
-    return ((value << bits) & 0xFFFFFFFF) | (value >> (32 - bits))
-}
-
-class MD5: HashProtocol {
-    
-    static let size = 16 // 128 / 8
-    let message: [UInt8]
-    
-    init (_ message: [UInt8]) {
-        self.message = message
-    }
-    
-    /** specifies the per-round shift amounts */
-    private let shifts: [UInt32] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
-                                    5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
-                                    4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
-                                    6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]
-    
-    /** binary integer part of the sines of integers (Radians) */
-    private let sines: [UInt32] = [0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
-                               0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
-                               0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
-                               0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
-                               0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
-                               0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
-                               0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
-                               0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
-                               0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
-                               0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
-                               0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
-                               0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
-                               0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
-                               0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
-                               0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
-                               0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391]
-    
-    private let hashes: [UInt32] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]
-    
-    func calculate() -> [UInt8] {
-        var tmpMessage = prepare(64)
-        tmpMessage.reserveCapacity(tmpMessage.count + 4)
-        
-        // hash values
-        var hh = hashes
-        
-        // Step 2. Append Length a 64-bit representation of lengthInBits
-        let lengthInBits = (message.count * 8)
-        let lengthBytes = lengthInBits.bytes(64 / 8)
-        tmpMessage += lengthBytes.reversed()
-
-        // Process the message in successive 512-bit chunks:
-        let chunkSizeBytes = 512 / 8 // 64
-
-        for chunk in BytesSequence(chunkSize: chunkSizeBytes, data: tmpMessage) {
-            // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
-            var M = toUInt32Array(chunk)
-            assert(M.count == 16, "Invalid array")
-            
-            // Initialize hash value for this chunk:
-            var A: UInt32 = hh[0]
-            var B: UInt32 = hh[1]
-            var C: UInt32 = hh[2]
-            var D: UInt32 = hh[3]
-            
-            var dTemp: UInt32 = 0
-            
-            // Main loop
-            for j in 0 ..< sines.count {
-                var g = 0
-                var F: UInt32 = 0
-                
-                switch j {
-                case 0...15:
-                    F = (B & C) | ((~B) & D)
-                    g = j
-                    break
-                case 16...31:
-                    F = (D & B) | (~D & C)
-                    g = (5 * j + 1) % 16
-                    break
-                case 32...47:
-                    F = B ^ C ^ D
-                    g = (3 * j + 5) % 16
-                    break
-                case 48...63:
-                    F = C ^ (B | (~D))
-                    g = (7 * j) % 16
-                    break
-                default:
-                    break
-                }
-                dTemp = D
-                D = C
-                C = B
-                B = B &+ rotateLeft((A &+ F &+ sines[j] &+ M[g]), bits: shifts[j])
-                A = dTemp
-            }
-            
-            hh[0] = hh[0] &+ A
-            hh[1] = hh[1] &+ B
-            hh[2] = hh[2] &+ C
-            hh[3] = hh[3] &+ D
-        }
-        
-        var result = [UInt8]()
-        result.reserveCapacity(hh.count / 4)
-        
-        hh.forEach {
-            let itemLE = $0.littleEndian
-            let r1 = UInt8(itemLE & 0xff)
-            let r2 = UInt8((itemLE >> 8) & 0xff)
-            let r3 = UInt8((itemLE >> 16) & 0xff)
-            let r4 = UInt8((itemLE >> 24) & 0xff)
-            result += [r1, r2, r3, r4]
-        }
-        return result
-    }
-}

+ 0 - 40
Example/Pods/Kingfisher/Sources/ThreadHelper.swift

@@ -1,40 +0,0 @@
-//
-//  ThreadHelper.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 15/10/9.
-//
-//  Copyright (c) 2018 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.
-
-import Foundation
-
-extension DispatchQueue {
-    // This method will dispatch the `block` to self.
-    // If `self` is the main queue, and current thread is main thread, the block
-    // will be invoked immediately instead of being dispatched.
-    func safeAsync(_ block: @escaping ()->()) {
-        if self === DispatchQueue.main && Thread.isMainThread {
-            block()
-        } else {
-            async { block() }
-        }
-    }
-}

+ 0 - 274
Example/Pods/Kingfisher/Sources/UIButton+Kingfisher.swift

@@ -1,274 +0,0 @@
-//
-//  UIButton+Kingfisher.swift
-//  Kingfisher
-//
-//  Created by Wei Wang on 15/4/13.
-//
-//  Copyright (c) 2018 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.
-
-import UIKit
-
-// MARK: - Set Images
-/**
- *	Set image to use in button from web for a specified state.
- */
-extension Kingfisher where Base: UIButton {
-    /**
-     Set an image to use for a specified state with a resource, a placeholder image, options, progress handler and
-     completion handler.
-     
-     - parameter resource:          Resource object contains information such as `cacheKey` and `downloadURL`.
-     - parameter state:             The state that uses the specified image.
-     - parameter placeholder:       A placeholder image when retrieving the image at URL.
-     - parameter options:           A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
-     - parameter progressBlock:     Called when the image downloading progress gets updated.
-     - parameter completionHandler: Called when the image retrieved and set.
-     
-     - returns: A task represents the retrieving process.
-     
-     - note: Both the `progressBlock` and `completionHandler` will be invoked in main thread.
-     The `CallbackDispatchQueue` specified in `optionsInfo` will not be used in callbacks of this method.
-     
-     If `resource` is `nil`, the `placeholder` image will be set and
-     `completionHandler` will be called with both `error` and `image` being `nil`.
-     */
-    @discardableResult
-    public func setImage(with resource: Resource?,
-                         for state: UIControl.State,
-                         placeholder: UIImage? = nil,
-                         options: KingfisherOptionsInfo? = nil,
-                         progressBlock: DownloadProgressBlock? = nil,
-                         completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
-    {
-        guard let resource = resource else {
-            base.setImage(placeholder, for: state)
-            setWebURL(nil, for: state)
-            completionHandler?(nil, nil, .none, nil)
-            return .empty
-        }
-        
-        let options = KingfisherManager.shared.defaultOptions + (options ?? KingfisherEmptyOptionsInfo)
-        if !options.keepCurrentImageWhileLoading {
-            base.setImage(placeholder, for: state)
-        }
-        
-        setWebURL(resource.downloadURL, for: state)
-        let task = KingfisherManager.shared.retrieveImage(
-            with: resource,
-            options: options,
-            progressBlock: { receivedSize, totalSize in
-                guard resource.downloadURL == self.webURL(for: state) else {
-                    return
-                }
-                if let progressBlock = progressBlock {
-                    progressBlock(receivedSize, totalSize)
-                }
-            },
-            completionHandler: {[weak base] image, error, cacheType, imageURL in
-                DispatchQueue.main.safeAsync {
-                    guard let strongBase = base, imageURL == self.webURL(for: state) else {
-                        completionHandler?(image, error, cacheType, imageURL)
-                        return
-                    }
-                    self.setImageTask(nil)
-                    if image != nil {
-                        strongBase.setImage(image, for: state)
-                    }
-
-                    completionHandler?(image, error, cacheType, imageURL)
-                }
-            })
-        
-        setImageTask(task)
-        return task
-    }
-    
-    /**
-     Cancel the image download task bounded to the image view if it is running.
-     Nothing will happen if the downloading has already finished.
-     */
-    public func cancelImageDownloadTask() {
-        imageTask?.cancel()
-    }
-    
-    /**
-     Set the background image to use for a specified state with a resource,
-     a placeholder image, options progress handler and completion handler.
-     
-     - parameter resource:          Resource object contains information such as `cacheKey` and `downloadURL`.
-     - parameter state:             The state that uses the specified image.
-     - parameter placeholder:       A placeholder image when retrieving the image at URL.
-     - parameter options:           A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
-     - parameter progressBlock:     Called when the image downloading progress gets updated.
-     - parameter completionHandler: Called when the image retrieved and set.
-     
-     - returns: A task represents the retrieving process.
-     
-     - note: Both the `progressBlock` and `completionHandler` will be invoked in main thread.
-     The `CallbackDispatchQueue` specified in `optionsInfo` will not be used in callbacks of this method.
-     
-     If `resource` is `nil`, the `placeholder` image will be set and
-     `completionHandler` will be called with both `error` and `image` being `nil`.
-     */
-    @discardableResult
-    public func setBackgroundImage(with resource: Resource?,
-                                   for state: UIControl.State,
-                                   placeholder: UIImage? = nil,
-                                   options: KingfisherOptionsInfo? = nil,
-                                   progressBlock: DownloadProgressBlock? = nil,
-                                   completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
-    {
-        guard let resource = resource else {
-            base.setBackgroundImage(placeholder, for: state)
-            setBackgroundWebURL(nil, for: state)
-            completionHandler?(nil, nil, .none, nil)
-            return .empty
-        }
-        
-        let options = KingfisherManager.shared.defaultOptions + (options ?? KingfisherEmptyOptionsInfo)
-        if !options.keepCurrentImageWhileLoading {
-            base.setBackgroundImage(placeholder, for: state)
-        }
-        
-        setBackgroundWebURL(resource.downloadURL, for: state)
-        let task = KingfisherManager.shared.retrieveImage(
-            with: resource,
-            options: options,
-            progressBlock: { receivedSize, totalSize in
-                guard resource.downloadURL == self.backgroundWebURL(for: state) else {
-                    return
-                }
-                if let progressBlock = progressBlock {
-                    progressBlock(receivedSize, totalSize)
-                }
-            },
-            completionHandler: { [weak base] image, error, cacheType, imageURL in
-                DispatchQueue.main.safeAsync {
-                    guard let strongBase = base, imageURL == self.backgroundWebURL(for: state) else {
-                        completionHandler?(image, error, cacheType, imageURL)
-                        return
-                    }
-                    self.setBackgroundImageTask(nil)
-                    if image != nil {
-                        strongBase.setBackgroundImage(image, for: state)
-                    }
-                    completionHandler?(image, error, cacheType, imageURL)
-                }
-            })
-        
-        setBackgroundImageTask(task)
-        return task
-    }
-    
-    /**
-     Cancel the background image download task bounded to the image view if it is running.
-     Nothing will happen if the downloading has already finished.
-     */
-    public func cancelBackgroundImageDownloadTask() {
-        backgroundImageTask?.cancel()
-    }
-
-}
-
-// MARK: - Associated Object
-private var lastURLKey: Void?
-private var imageTaskKey: Void?
-
-extension Kingfisher where Base: UIButton {
-    /**
-     Get the image URL binded to this button for a specified state.
-     
-     - parameter state: The state that uses the specified image.
-     
-     - returns: Current URL for image.
-     */
-    public func webURL(for state: UIControl.State) -> URL? {
-        return webURLs[NSNumber(value:state.rawValue)] as? URL
-    }
-    
-    fileprivate func setWebURL(_ url: URL?, for state: UIControl.State) {
-        webURLs[NSNumber(value:state.rawValue)] = url
-    }
-    
-    fileprivate var webURLs: NSMutableDictionary {
-        var dictionary = objc_getAssociatedObject(base, &lastURLKey) as? NSMutableDictionary
-        if dictionary == nil {
-            dictionary = NSMutableDictionary()
-            setWebURLs(dictionary!)
-        }
-        return dictionary!
-    }
-    
-    fileprivate func setWebURLs(_ URLs: NSMutableDictionary) {
-        objc_setAssociatedObject(base, &lastURLKey, URLs, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-    }
-    
-    fileprivate var imageTask: RetrieveImageTask? {
-        return objc_getAssociatedObject(base, &imageTaskKey) as? RetrieveImageTask
-    }
-    
-    fileprivate func setImageTask(_ task: RetrieveImageTask?) {
-        objc_setAssociatedObject(base, &imageTaskKey, task, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-    }
-}
-
-
-private var lastBackgroundURLKey: Void?
-private var backgroundImageTaskKey: Void?
-
-
-extension Kingfisher where Base: UIButton {
-    /**
-     Get the background image URL binded to this button for a specified state.
-     
-     - parameter state: The state that uses the specified background image.
-     
-     - returns: Current URL for background image.
-     */
-    public func backgroundWebURL(for state: UIControl.State) -> URL? {
-        return backgroundWebURLs[NSNumber(value:state.rawValue)] as? URL
-    }
-    
-    fileprivate func setBackgroundWebURL(_ url: URL?, for state: UIControl.State) {
-        backgroundWebURLs[NSNumber(value:state.rawValue)] = url
-    }
-    
-    fileprivate var backgroundWebURLs: NSMutableDictionary {
-        var dictionary = objc_getAssociatedObject(base, &lastBackgroundURLKey) as? NSMutableDictionary
-        if dictionary == nil {
-            dictionary = NSMutableDictionary()
-            setBackgroundWebURLs(dictionary!)
-        }
-        return dictionary!
-    }
-    
-    fileprivate func setBackgroundWebURLs(_ URLs: NSMutableDictionary) {
-        objc_setAssociatedObject(base, &lastBackgroundURLKey, URLs, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-    }
-    
-    fileprivate var backgroundImageTask: RetrieveImageTask? {
-        return objc_getAssociatedObject(base, &backgroundImageTaskKey) as? RetrieveImageTask
-    }
-    
-    fileprivate func setBackgroundImageTask(_ task: RetrieveImageTask?) {
-        objc_setAssociatedObject(base, &backgroundImageTaskKey, task, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-    }
-}

+ 0 - 28
Example/Pods/KingfisherWebP/KingfisherWebP/Classes/CGImage+WebP.h

@@ -1,28 +0,0 @@
-//
-//  CGImage+WebP.h
-//  Pods
-//
-//  Created by yeatse on 2016/10/20.
-//
-//
-
-#import <CoreGraphics/CoreGraphics.h>
-
-CF_IMPLICIT_BRIDGING_ENABLED
-CF_ASSUME_NONNULL_BEGIN
-
-// still image
-CGImageRef __nullable WebPImageCreateWithData(CFDataRef webpData);
-CFDataRef __nullable WebPDataCreateWithImage(CGImageRef image);
-
-// animated image
-CG_EXTERN const CFStringRef kWebPAnimatedImageDuration;
-CG_EXTERN const CFStringRef kWebPAnimatedImageLoopCount;
-CG_EXTERN const CFStringRef kWebPAnimatedImageFrames; // CFArrayRef of CGImageRef
-
-NSUInteger WebPImageFrameCountGetFromData(CFDataRef webpData);
-CFDictionaryRef __nullable WebPAnimatedImageInfoCreateWithData(CFDataRef webpData);
-CFDataRef __nullable WebPDataCreateWithAnimatedImageInfo(CFDictionaryRef imageInfo);
-
-CF_ASSUME_NONNULL_END
-CF_IMPLICIT_BRIDGING_DISABLED

+ 0 - 447
Example/Pods/KingfisherWebP/KingfisherWebP/Classes/CGImage+WebP.m

@@ -1,447 +0,0 @@
-//
-//  CGImage+WebP.m
-//  Pods
-//
-//  Created by yeatse on 2016/10/20.
-//
-//
-
-#import "CGImage+WebP.h"
-
-#import <Accelerate/Accelerate.h>
-#import "webp/decode.h"
-#import "webp/encode.h"
-#import "webp/demux.h"
-#import "webp/mux.h"
-
-#pragma mark - Helper Functions
-
-static void WebPFreeInfoReleaseDataCallback(void *info, const void *data, size_t size) {
-    if (info) {
-        free(info);
-    }
-}
-
-static CGColorSpaceRef WebPColorSpaceForDeviceRGB() {
-    static CGColorSpaceRef colorSpace;
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        colorSpace = CGColorSpaceCreateDeviceRGB();
-    });
-    return colorSpace;
-}
-
-/**
- Decode an image to bitmap buffer with the specified format.
- 
- @param srcImage   Source image.
- @param dest       Destination buffer. It should be zero before call this method.
- If decode succeed, you should release the dest->data using free().
- @param destFormat Destination bitmap format.
- 
- @return Whether succeed.
- 
- @warning This method support iOS7.0 and later. If call it on iOS6, it just returns NO.
- CG_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0)
- */
-static BOOL WebPCGImageDecodeToBitmapBufferWithAnyFormat(CGImageRef srcImage, vImage_Buffer *dest, vImage_CGImageFormat *destFormat) {
-    if (!srcImage || (((long)vImageConvert_AnyToAny) + 1 == 1) || !destFormat || !dest) return NO;
-    size_t width = CGImageGetWidth(srcImage);
-    size_t height = CGImageGetHeight(srcImage);
-    if (width == 0 || height == 0) return NO;
-    dest->data = NULL;
-    
-    vImage_Error error = kvImageNoError;
-    CFDataRef srcData = NULL;
-    vImageConverterRef convertor = NULL;
-    vImage_CGImageFormat srcFormat = {0};
-    srcFormat.bitsPerComponent = (uint32_t)CGImageGetBitsPerComponent(srcImage);
-    srcFormat.bitsPerPixel = (uint32_t)CGImageGetBitsPerPixel(srcImage);
-    srcFormat.colorSpace = CGImageGetColorSpace(srcImage);
-    srcFormat.bitmapInfo = CGImageGetBitmapInfo(srcImage) | CGImageGetAlphaInfo(srcImage);
-    
-    convertor = vImageConverter_CreateWithCGImageFormat(&srcFormat, destFormat, NULL, kvImageNoFlags, NULL);
-    if (!convertor) goto fail;
-    
-    CGDataProviderRef srcProvider = CGImageGetDataProvider(srcImage);
-    srcData = srcProvider ? CGDataProviderCopyData(srcProvider) : NULL; // decode
-    size_t srcLength = srcData ? CFDataGetLength(srcData) : 0;
-    const void *srcBytes = srcData ? CFDataGetBytePtr(srcData) : NULL;
-    if (srcLength == 0 || !srcBytes) goto fail;
-    
-    vImage_Buffer src = {0};
-    src.data = (void *)srcBytes;
-    src.width = width;
-    src.height = height;
-    src.rowBytes = CGImageGetBytesPerRow(srcImage);
-    
-    error = vImageBuffer_Init(dest, height, width, 32, kvImageNoFlags);
-    if (error != kvImageNoError) goto fail;
-    
-    error = vImageConvert_AnyToAny(convertor, &src, dest, NULL, kvImageNoFlags); // convert
-    if (error != kvImageNoError) goto fail;
-    
-    CFRelease(convertor);
-    CFRelease(srcData);
-    return YES;
-    
-fail:
-    if (convertor) CFRelease(convertor);
-    if (srcData) CFRelease(srcData);
-    if (dest->data) free(dest->data);
-    dest->data = NULL;
-    return NO;
-}
-
-/**
- Decode an image to bitmap buffer with the 32bit format (such as ARGB8888).
- 
- @param srcImage   Source image.
- @param dest       Destination buffer. It should be zero before call this method.
- If decode succeed, you should release the dest->data using free().
- @param bitmapInfo Destination bitmap format.
- 
- @return Whether succeed.
- */
-static BOOL WebPCGImageDecodeToBitmapBufferWith32BitFormat(CGImageRef srcImage, vImage_Buffer *dest, CGBitmapInfo bitmapInfo) {
-    if (!srcImage || !dest) return NO;
-    size_t width = CGImageGetWidth(srcImage);
-    size_t height = CGImageGetHeight(srcImage);
-    if (width == 0 || height == 0) return NO;
-    
-    BOOL hasAlpha = NO;
-    BOOL alphaFirst = NO;
-    BOOL alphaPremultiplied = NO;
-    BOOL byteOrderNormal = NO;
-    
-    switch (bitmapInfo & kCGBitmapAlphaInfoMask) {
-        case kCGImageAlphaPremultipliedLast: {
-            hasAlpha = YES;
-            alphaPremultiplied = YES;
-        } break;
-        case kCGImageAlphaPremultipliedFirst: {
-            hasAlpha = YES;
-            alphaPremultiplied = YES;
-            alphaFirst = YES;
-        } break;
-        case kCGImageAlphaLast: {
-            hasAlpha = YES;
-        } break;
-        case kCGImageAlphaFirst: {
-            hasAlpha = YES;
-            alphaFirst = YES;
-        } break;
-        case kCGImageAlphaNoneSkipLast: {
-        } break;
-        case kCGImageAlphaNoneSkipFirst: {
-            alphaFirst = YES;
-        } break;
-        default: {
-            return NO;
-        } break;
-    }
-    
-    switch (bitmapInfo & kCGBitmapByteOrderMask) {
-        case kCGBitmapByteOrderDefault: {
-            byteOrderNormal = YES;
-        } break;
-        case kCGBitmapByteOrder32Little: {
-        } break;
-        case kCGBitmapByteOrder32Big: {
-            byteOrderNormal = YES;
-        } break;
-        default: {
-            return NO;
-        } break;
-    }
-    
-    /*
-     Try convert with vImageConvert_AnyToAny() (avaliable since iOS 7.0).
-     If fail, try decode with CGContextDrawImage().
-     CGBitmapContext use a premultiplied alpha format, unpremultiply may lose precision.
-     */
-    vImage_CGImageFormat destFormat = {0};
-    destFormat.bitsPerComponent = 8;
-    destFormat.bitsPerPixel = 32;
-    destFormat.colorSpace = WebPColorSpaceForDeviceRGB();
-    destFormat.bitmapInfo = bitmapInfo;
-    dest->data = NULL;
-    if (WebPCGImageDecodeToBitmapBufferWithAnyFormat(srcImage, dest, &destFormat)) return YES;
-    
-    CGBitmapInfo contextBitmapInfo = bitmapInfo & kCGBitmapByteOrderMask;
-    if (!hasAlpha || alphaPremultiplied) {
-        contextBitmapInfo |= (bitmapInfo & kCGBitmapAlphaInfoMask);
-    } else {
-        contextBitmapInfo |= alphaFirst ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaPremultipliedLast;
-    }
-    CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, WebPColorSpaceForDeviceRGB(), contextBitmapInfo);
-    if (!context) goto fail;
-    
-    CGContextDrawImage(context, CGRectMake(0, 0, width, height), srcImage); // decode and convert
-    size_t bytesPerRow = CGBitmapContextGetBytesPerRow(context);
-    size_t length = height * bytesPerRow;
-    void *data = CGBitmapContextGetData(context);
-    if (length == 0 || !data) goto fail;
-    
-    dest->data = malloc(length);
-    dest->width = width;
-    dest->height = height;
-    dest->rowBytes = bytesPerRow;
-    if (!dest->data) goto fail;
-    
-    if (hasAlpha && !alphaPremultiplied) {
-        vImage_Buffer tmpSrc = {0};
-        tmpSrc.data = data;
-        tmpSrc.width = width;
-        tmpSrc.height = height;
-        tmpSrc.rowBytes = bytesPerRow;
-        vImage_Error error;
-        if (alphaFirst && byteOrderNormal) {
-            error = vImageUnpremultiplyData_ARGB8888(&tmpSrc, dest, kvImageNoFlags);
-        } else {
-            error = vImageUnpremultiplyData_RGBA8888(&tmpSrc, dest, kvImageNoFlags);
-        }
-        if (error != kvImageNoError) goto fail;
-    } else {
-        memcpy(dest->data, data, length);
-    }
-    
-    CFRelease(context);
-    return YES;
-    
-fail:
-    if (context) CFRelease(context);
-    if (dest->data) free(dest->data);
-    dest->data = NULL;
-    return NO;
-    return NO;
-}
-
-static int WebPPictureImportCGImage(WebPPicture *picture, CGImageRef image) {
-    vImage_Buffer buffer = {0};
-    int result = 0;
-    if (WebPCGImageDecodeToBitmapBufferWith32BitFormat(image, &buffer, kCGImageAlphaLast | kCGBitmapByteOrderDefault)) {
-        picture->width = (int)buffer.width;
-        picture->height = (int)buffer.height;
-        picture->use_argb = 1;
-        result = WebPPictureImportRGBA(picture, buffer.data, (int)buffer.rowBytes);
-        free(buffer.data);
-    }
-    return result;
-}
-
-#pragma mark - Still Images
-
-CGImageRef WebPImageCreateWithData(CFDataRef webpData) {
-    WebPData webp_data;
-    WebPDataInit(&webp_data);
-    webp_data.bytes = CFDataGetBytePtr(webpData);
-    webp_data.size = CFDataGetLength(webpData);
-    
-    WebPAnimDecoderOptions dec_options;
-    WebPAnimDecoderOptionsInit(&dec_options);
-    dec_options.use_threads = 1;
-    dec_options.color_mode = MODE_rgbA;
-    
-    WebPAnimDecoder *dec = WebPAnimDecoderNew(&webp_data, &dec_options);
-    if (!dec) {
-        return NULL;
-    }
-    
-    WebPAnimInfo anim_info;
-    uint8_t *buf;
-    int timestamp;
-    if (!WebPAnimDecoderGetInfo(dec, &anim_info) || !WebPAnimDecoderGetNext(dec, &buf, &timestamp)) {
-        WebPAnimDecoderDelete(dec);
-        return NULL;
-    }
-    
-    const size_t bufSize = anim_info.canvas_width * 4 * anim_info.canvas_height;
-    void *bufCopy = malloc(bufSize);
-    memcpy(bufCopy, buf, bufSize);
-    WebPAnimDecoderDelete(dec);
-        
-    CGDataProviderRef provider = CGDataProviderCreateWithData(bufCopy, bufCopy, bufSize, WebPFreeInfoReleaseDataCallback);
-    CGImageRef image = CGImageCreate(anim_info.canvas_width, anim_info.canvas_height, 8, 32, anim_info.canvas_width * 4, WebPColorSpaceForDeviceRGB(), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault, provider, NULL, false, kCGRenderingIntentDefault);
-    CGDataProviderRelease(provider);
-    
-    return image;
-}
-
-CFDataRef WebPDataCreateWithImage(CGImageRef image) {
-    WebPConfig config;
-    WebPConfigInit(&config);
-    WebPConfigLosslessPreset(&config, 0);
-    
-    WebPPicture picture;
-    WebPPictureInit(&picture);
-    
-    WebPMemoryWriter writer;
-    WebPMemoryWriterInit(&writer);
-    picture.writer = WebPMemoryWrite;
-    picture.custom_ptr = &writer;
-    
-    if (!(WebPPictureImportCGImage(&picture, image))) {
-        goto fail;
-    }
-    
-    if (!WebPEncode(&config, &picture)) {
-        goto fail;
-    }
-    
-    CFDataRef data = CFDataCreate(kCFAllocatorDefault, writer.mem, writer.size);
-    WebPMemoryWriterClear(&writer);
-    WebPPictureFree(&picture);
-    return data;
-    
-fail:
-    WebPMemoryWriterClear(&writer);
-    WebPPictureFree(&picture);
-    return NULL;
-}
-
-#pragma mark - Animated Images
-
-const CFStringRef kWebPAnimatedImageDuration = CFSTR("kWebPAnimatedImageDuration");
-const CFStringRef kWebPAnimatedImageLoopCount = CFSTR("kWebPAnimatedImageLoopCount");
-const CFStringRef kWebPAnimatedImageFrames = CFSTR("kWebPAnimatedImageFrames");
-
-NSUInteger WebPImageFrameCountGetFromData(CFDataRef webpData) {
-    WebPData webp_data;
-    WebPDataInit(&webp_data);
-    webp_data.bytes = CFDataGetBytePtr(webpData);
-    webp_data.size = CFDataGetLength(webpData);
-    
-    WebPDemuxer *dmux = WebPDemux(&webp_data);
-    if (!dmux) {
-        return 0;
-    }
-    
-    NSUInteger frameCount = WebPDemuxGetI(dmux, WEBP_FF_FRAME_COUNT);
-    WebPDemuxDelete(dmux);
-    
-    return frameCount;
-}
-
-CFDictionaryRef WebPAnimatedImageInfoCreateWithData(CFDataRef webpData) {
-    WebPData webp_data;
-    WebPDataInit(&webp_data);
-    webp_data.bytes = CFDataGetBytePtr(webpData);
-    webp_data.size = CFDataGetLength(webpData);
-    
-    WebPAnimDecoderOptions dec_options;
-    WebPAnimDecoderOptionsInit(&dec_options);
-    dec_options.use_threads = 1;
-    dec_options.color_mode = MODE_rgbA;
-    
-    WebPAnimDecoder *dec = WebPAnimDecoderNew(&webp_data, &dec_options);
-    if (!dec) {
-        return NULL;
-    }
-    
-    WebPAnimInfo anim_info;
-    if (!WebPAnimDecoderGetInfo(dec, &anim_info)) {
-        WebPAnimDecoderDelete(dec);
-        return NULL;
-    }
-    
-    CFMutableDictionaryRef imageInfo = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-    
-    CFMutableArrayRef imageFrames = CFArrayCreateMutable(kCFAllocatorDefault, anim_info.frame_count, &kCFTypeArrayCallBacks);
-    
-    int duration = 0;
-    while (WebPAnimDecoderHasMoreFrames(dec)) {
-        uint8_t *buf;
-        
-        if (!WebPAnimDecoderGetNext(dec, &buf, &duration)) {
-            break;
-        }
-        
-        const size_t bufSize = anim_info.canvas_width * 4 * anim_info.canvas_height;
-        void *bufCopy = malloc(bufSize);
-        memcpy(bufCopy, buf, bufSize);
-        
-        CGDataProviderRef provider = CGDataProviderCreateWithData(bufCopy, bufCopy, bufSize, WebPFreeInfoReleaseDataCallback);
-        CGImageRef image = CGImageCreate(anim_info.canvas_width, anim_info.canvas_height, 8, 32, anim_info.canvas_width * 4, WebPColorSpaceForDeviceRGB(), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault, provider, NULL, false, kCGRenderingIntentDefault);
-        CFArrayAppendValue(imageFrames, image);
-        CGImageRelease(image);
-        CGDataProviderRelease(provider);
-    }
-    
-    // add last frame's duration
-    const WebPDemuxer *dmux = WebPAnimDecoderGetDemuxer(dec);
-    WebPIterator iter;
-    if (WebPDemuxGetFrame(dmux, 0, &iter)) {
-        duration += iter.duration;
-        WebPDemuxReleaseIterator(&iter);
-    }
-    WebPAnimDecoderDelete(dec);
-    
-    CFDictionarySetValue(imageInfo, kWebPAnimatedImageFrames, imageFrames);
-    CFRelease(imageFrames);
-    
-    CFNumberRef loopCount = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &anim_info.loop_count);
-    CFDictionarySetValue(imageInfo, kWebPAnimatedImageLoopCount, loopCount);
-    CFRelease(loopCount);
-    
-    double durationInSec = ((double)duration) / 1000;
-    CFNumberRef durationRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &durationInSec);
-    CFDictionarySetValue(imageInfo, kWebPAnimatedImageDuration, durationRef);
-    CFRelease(durationRef);
-    
-    return imageInfo;
-}
-
-
-
-CFDataRef WebPDataCreateWithAnimatedImageInfo(CFDictionaryRef imageInfo) {
-    CFNumberRef loopCount = CFDictionaryGetValue(imageInfo, kWebPAnimatedImageLoopCount);
-    CFNumberRef durationRef = CFDictionaryGetValue(imageInfo, kWebPAnimatedImageDuration);
-    CFArrayRef imageFrames = CFDictionaryGetValue(imageInfo, kWebPAnimatedImageFrames);
-    
-    if (!imageFrames || CFArrayGetCount(imageFrames) < 1) {
-        return NULL;
-    }
-    
-    WebPAnimEncoderOptions enc_options;
-    WebPAnimEncoderOptionsInit(&enc_options);
-    if (loopCount) {
-        CFNumberGetValue(loopCount, kCFNumberSInt32Type, &enc_options.anim_params.loop_count);
-    }
-    
-    CGImageRef firstImage = (CGImageRef)CFArrayGetValueAtIndex(imageFrames, 0);
-    WebPAnimEncoder *enc = WebPAnimEncoderNew((int)CGImageGetWidth(firstImage), (int)CGImageGetHeight(firstImage), &enc_options);
-    if (!enc) {
-        return NULL;
-    }
-    
-    int frameDurationInMilliSec = 100;
-    if (durationRef) {
-        double totalDurationInSec;
-        CFNumberGetValue(durationRef, kCFNumberDoubleType, &totalDurationInSec);
-        frameDurationInMilliSec = (int)(totalDurationInSec * 1000 / CFArrayGetCount(imageFrames));
-    }
-    
-    for (CFIndex i = 0; i < CFArrayGetCount(imageFrames); i ++) {
-        WebPPicture frame;
-        WebPPictureInit(&frame);
-        if (WebPPictureImportCGImage(&frame, (CGImageRef)CFArrayGetValueAtIndex(imageFrames, i))) {
-            WebPConfig config;
-            WebPConfigInit(&config);
-            WebPConfigLosslessPreset(&config, 0);
-            WebPAnimEncoderAdd(enc, &frame, (int)(frameDurationInMilliSec * i), &config);
-        }
-        WebPPictureFree(&frame);
-    }
-    WebPAnimEncoderAdd(enc, NULL, (int)(frameDurationInMilliSec * CFArrayGetCount(imageFrames)), NULL);
-    
-    WebPData webp_data;
-    WebPDataInit(&webp_data);
-    WebPAnimEncoderAssemble(enc, &webp_data);
-    WebPAnimEncoderDelete(enc);
-    
-    CFDataRef data = CFDataCreate(kCFAllocatorDefault, webp_data.bytes, webp_data.size);
-    WebPDataClear(&webp_data);
-    
-    return data;
-}

+ 0 - 88
Example/Pods/KingfisherWebP/KingfisherWebP/Classes/Image+WebP.swift

@@ -1,88 +0,0 @@
-//
-//  Image+WebP.swift
-//  Pods
-//
-//  Created by yeatse on 2016/10/19.
-//
-//
-
-import Kingfisher
-import KingfisherWebP.Private
-
-// MARK: - Image Representation
-extension Kingfisher where Base: Image {
-    public func webpRepresentation() -> Data? {
-        if let result = animatedWebPRepresentation() {
-            return result
-        }
-        if let cgImage = base.cgImage {
-            return WebPDataCreateWithImage(cgImage) as Data?
-        }
-        return nil
-    }
-    
-    private func animatedWebPRepresentation() -> Data? {
-        #if swift(>=4.1)
-        guard let images = base.images?.compactMap({ $0.cgImage }) else {
-            return nil
-        }
-        #else
-        guard let images = base.images?.flatMap({ $0.cgImage }) else {
-            return nil
-        }
-        #endif
-        let imageInfo = [ kWebPAnimatedImageFrames: images,
-                          kWebPAnimatedImageDuration: NSNumber(value: base.duration) ] as [CFString : Any]
-        return WebPDataCreateWithAnimatedImageInfo(imageInfo as CFDictionary) as Data?
-    }
-}
-
-// MARK: - Create image from WebP data
-extension Kingfisher where Base: Image {
-    static func image(webpData: Data, scale: CGFloat, onlyFirstFrame: Bool) -> Image? {
-        let frameCount = WebPImageFrameCountGetFromData(webpData as CFData)
-        if (frameCount == 0) {
-            return nil
-        }
-        
-        if (frameCount == 1 || onlyFirstFrame) {
-            guard let cgImage = WebPImageCreateWithData(webpData as CFData) else {
-                return nil
-            }
-            return Image(cgImage: cgImage, scale: scale, orientation: .up)
-        }
-        
-        // MARK: Animated images
-        guard let animationInfo = WebPAnimatedImageInfoCreateWithData(webpData as CFData) as Dictionary? else {
-            return nil
-        }
-        guard let cgFrames = animationInfo[kWebPAnimatedImageFrames] as? [CGImage] else {
-            return nil
-        }
-        let uiFrames = cgFrames.map { Image(cgImage: $0, scale: scale, orientation: .up) }
-        
-        let duration = (animationInfo[kWebPAnimatedImageDuration] as? NSNumber).flatMap { $0.doubleValue as TimeInterval } ?? 0.1 * TimeInterval(frameCount)
-        return Image.animatedImage(with: uiFrames, duration: duration)
-    }
-}
-
-// MARK: - WebP Format Testing
-extension Data {
-    public var isWebPFormat: Bool {
-        if count < 12 {
-            return false
-        }
-
-        let endIndex = index(startIndex, offsetBy: 12)
-        let testData = subdata(in: startIndex..<endIndex)
-        guard let testString = String(data: testData, encoding: .ascii) else {
-            return false
-        }
-
-        if testString.hasPrefix("RIFF") && testString.hasSuffix("WEBP") {
-            return true
-        } else {
-            return false
-        }
-    }
-}

+ 0 - 16
Example/Pods/KingfisherWebP/KingfisherWebP/Classes/KingfisherWebP-umbrella.h

@@ -1,16 +0,0 @@
-#ifdef __OBJC__
-#import <UIKit/UIKit.h>
-#else
-#ifndef FOUNDATION_EXPORT
-#if defined(__cplusplus)
-#define FOUNDATION_EXPORT extern "C"
-#else
-#define FOUNDATION_EXPORT extern
-#endif
-#endif
-#endif
-
-
-FOUNDATION_EXPORT double KingfisherWebPVersionNumber;
-FOUNDATION_EXPORT const unsigned char KingfisherWebPVersionString[];
-

+ 0 - 32
Example/Pods/KingfisherWebP/KingfisherWebP/Classes/WebPProcessor.swift

@@ -1,32 +0,0 @@
-//
-//  WebPProcessor.swift
-//  Pods
-//
-//  Created by yeatse on 2016/10/19.
-//
-//
-
-import Foundation
-import Kingfisher
-
-public struct WebPProcessor: ImageProcessor {
-    public static let `default` = WebPProcessor()
-
-    public let identifier = "com.yeatse.WebPProcessor"
-
-    public init() {}
-
-    public func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
-        switch item {
-        case .image(let image):
-            return image
-        case .data(let data):
-            if data.isWebPFormat {
-                return Kingfisher<Image>.image(webpData: data, scale: options.scaleFactor, onlyFirstFrame: options.onlyLoadFirstFrame)
-            } else {
-                return DefaultImageProcessor.default.process(item: item, options: options)
-            }
-        }
-    }
-}
-

+ 0 - 27
Example/Pods/KingfisherWebP/KingfisherWebP/Classes/WebPSerializer.swift

@@ -1,27 +0,0 @@
-//
-//  WebPSerializer.swift
-//  Pods
-//
-//  Created by yeatse on 2016/10/20.
-//
-//
-
-import Kingfisher
-
-public struct WebPSerializer: CacheSerializer {
-
-    public static let `default` = WebPSerializer()
-    private init() {}
-
-    public func data(with image: Image, original: Data?) -> Data? {
-        if let original = original, !original.isWebPFormat {
-            return DefaultCacheSerializer.default.data(with: image, original: original)
-        } else {
-            return image.kf.normalized.kf.webpRepresentation()
-        }
-    }
-
-    public func image(with data: Data, options: KingfisherOptionsInfo?) -> Image? {
-        return WebPProcessor.default.process(item: .data(data), options: options ?? [])
-    }
-}

+ 0 - 10
Example/Pods/KingfisherWebP/KingfisherWebP/KingfisherWebP.modulemap

@@ -1,10 +0,0 @@
-framework module KingfisherWebP {
-  umbrella header "KingfisherWebP-umbrella.h"
-
-  export *
-  module * { export * }
-
-  explicit module Private {
-    header "CGImage+WebP.h"
-  }
-}

+ 41 - 4
Example/Pods/KingfisherWebP/README.md

@@ -1,6 +1,6 @@
 # KingfisherWebP
 
-[![CI Status](http://img.shields.io/travis/Yeatse/KingfisherWebP.svg?style=flat)](https://travis-ci.org/Yeatse/KingfisherWebP)
+[![CI Status](https://github.com/Yeatse/KingfisherWebP/workflows/unittest/badge.svg)](https://travis-ci.org/Yeatse/KingfisherWebP)
 [![Version](https://img.shields.io/cocoapods/v/KingfisherWebP.svg?style=flat)](http://cocoapods.org/pods/KingfisherWebP)
 [![License](https://img.shields.io/cocoapods/l/KingfisherWebP.svg?style=flat)](http://cocoapods.org/pods/KingfisherWebP)
 [![Platform](https://img.shields.io/cocoapods/p/KingfisherWebP.svg?style=flat)](http://cocoapods.org/pods/KingfisherWebP)
@@ -20,12 +20,31 @@ For convenience, you may set it as a global default option to all `KingfisherMan
 
 ```swift
 // somewhere after your application launches...
-KingfisherManager.shared.defaultOptions = [.processor(WebPProcessor.default), .cacheSerializer(WebPSerializer.default)]
+
+KingfisherManager.shared.defaultOptions += [
+  .processor(WebPProcessor.default),
+  .cacheSerializer(WebPSerializer.default)
+]
 
 // You can now use webp in Kingfisher like any other format
 imageView.kf.setImage(with: url)
 ```
 
+Some image servers may expect the `"Accept"` header to include `"image/webp"`.
+You can include this header to all Kingfisher requests by doing:
+```swift
+let modifier = AnyModifier { request in
+    var req = request
+    req.addValue("image/webp */*", forHTTPHeaderField: "Accept")
+    return req
+}
+
+KingfisherManager.shared.defaultOptions += [
+    .requestModifier(modifier),
+    // ... other options
+]
+```
+
 If the image data is not in webp format, the default processor and serializer in `Kingfisher` will be used.
 
 
@@ -39,13 +58,31 @@ iOS 8 or above
 
 ## Installation
 
-KingfisherWebP is available through [CocoaPods](http://cocoapods.org). To install
-it, simply add the following line to your Podfile:
+### CocoaPods
+
+KingfisherWebP is available through [CocoaPods](http://cocoapods.org). To install it, simply add the following line to your Podfile:
 
 ```ruby
 pod "KingfisherWebP"
 ```
 
+### Swift Package Manager
+
+From Xcode 11, you can use [Swift Package Manager](https://swift.org/package-manager/) to add KingfisherWebP to your project. The "package repository url" of KingfisherWebP is `https://github.com/yeatse/KingfisherWebP.git`.
+
+![SPM screenshot](spm_screenshot.png)
+
+### Carthage
+
+You can also add KingfisherWebP using [Carthage](https://github.com/Carthage/Carthage). Note that KingfisherWebP is built on top of [libwebp](https://chromium.googlesource.com/webm/libwebp) project, so in your `Cartfile` you should add `libwebp` dependency as well:
+
+```
+github "yeatse/KingfisherWebP" ~> 1.3.0
+github "onevcat/Kingfisher" ~> 6.2.0
+github "SDWebImage/libwebp-Xcode" ~> 1.1.0
+```
+
+
 ## Author
 
 Yang Chao, iyeatse@gmail.com

+ 9 - 8
Example/Pods/Local Podspecs/BFFramework.podspec.json

@@ -1,6 +1,6 @@
 {
   "name": "BFFramework",
-  "version": "0.1.0",
+  "version": "0.1.1",
   "summary": "Byte fllow 基础组件库",
   "swift_versions": "5.0",
   "description": "TODO: Add long description of the pod here.",
@@ -32,7 +32,8 @@
     "VALIDATE_WORKSPACE_SKIPPED_SDK_FRAMEWORKS": "OpenGLES"
   },
   "pod_target_xcconfig": {
-    "OTHER_LDFLAGS": "-all_load"
+    "OTHER_LDFLAGS": "-all_load",
+    "VALID_ARCHS": "arm64 armv7"
   },
   "public_header_files": "BFFramework/Classes/**/*.h",
   "frameworks": [
@@ -50,7 +51,10 @@
       "4.2.0"
     ],
     "Kingfisher": [
-      "4.10.1"
+      "6.3.0"
+    ],
+    "KingfisherWebP": [
+      "1.3.0"
     ],
     "RealmSwift": [
       "10.7.2"
@@ -82,11 +86,8 @@
     "TXLiteAVSDK_Player": [
       "8.4.9944"
     ],
-    "NXFramework-Swift": [
-
-    ],
-    "KingfisherWebP": [
-      "0.4.2"
+    "Bugly": [
+      "2.5.90"
     ]
   },
   "swift_version": "5.0"

+ 5 - 1
Example/Pods/Manifest.lock

@@ -4,6 +4,7 @@ PODS:
   - BFFramework (0.1.1):
     - Alamofire (= 4.9.1)
     - AliyunOSSiOS (= 2.10.8)
+    - Bugly (= 2.5.90)
     - FDFullscreenPopGesture (= 1.1)
     - KeychainAccess (= 4.2.2)
     - Kingfisher (= 6.3.0)
@@ -16,6 +17,7 @@ PODS:
     - Toast-Swift (= 5.0.1)
     - TXLiteAVSDK_Player (= 8.4.9944)
     - WechatOpenSDK-Swift (= 1.8.7.1)
+  - Bugly (2.5.90)
   - FDFullscreenPopGesture (1.1)
   - KeychainAccess (4.2.2)
   - Kingfisher (6.3.0)
@@ -51,6 +53,7 @@ SPEC REPOS:
   trunk:
     - Alamofire
     - AliyunOSSiOS
+    - Bugly
     - FDFullscreenPopGesture
     - KeychainAccess
     - Kingfisher
@@ -73,7 +76,8 @@ EXTERNAL SOURCES:
 SPEC CHECKSUMS:
   Alamofire: 85e8a02c69d6020a0d734f6054870d7ecb75cf18
   AliyunOSSiOS: 8db92936545593b9e5c66d680ef2ac0738946651
-  BFFramework: a6a05169a9504af7ea4932b381e0c0494e77b8d9
+  BFFramework: c111f401f256a6459f5ffa146cedad5f304f48a9
+  Bugly: 88bc32c0acc6fef7b74d610f0319ee7560d6b9fe
   FDFullscreenPopGesture: a8a620179e3d9c40e8e00256dcee1c1a27c6d0f0
   KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51
   Kingfisher: 6c3df386db71d82c0817a429d2c9421a77396529

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1430 - 1383
Example/Pods/Pods.xcodeproj/project.pbxproj


+ 1 - 1
Example/Pods/Target Support Files/BFFramework/BFFramework-Info.plist

@@ -15,7 +15,7 @@
   <key>CFBundlePackageType</key>
   <string>FMWK</string>
   <key>CFBundleShortVersionString</key>
-  <string>0.1.0</string>
+  <string>0.1.1</string>
   <key>CFBundleSignature</key>
   <string>????</string>
   <key>CFBundleVersion</key>

+ 2 - 2
Example/Pods/Target Support Files/BFFramework/BFFramework-umbrella.h

@@ -11,14 +11,14 @@
 #endif
 
 #import "BFFramework_custom_umbrella.h"
+#import "UIControl+NXCategory.h"
+#import "PQBridgeObject.h"
 #import "GPUImage-Bridging-Header.h"
 #import "GPUImage.h"
 #import "NSObject+Exception.h"
 #import "NXAVUtil.h"
 #import "TPCircularBuffer.h"
 #import "UIImage+NXCategory.h"
-#import "UIControl+NXCategory.h"
-#import "PQBridgeObject.h"
 #import "DES3Util.h"
 #import "GTMBase64.h"
 #import "GTMDefines.h"

+ 2 - 1
Example/Pods/Target Support Files/BFFramework/BFFramework.debug.xcconfig

@@ -1,7 +1,7 @@
 CLANG_MODULES_AUTOLINK = YES
 CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
 CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/BFFramework
-FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/AliyunOSSiOS" "${PODS_CONFIGURATION_BUILD_DIR}/FDFullscreenPopGesture" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "${PODS_CONFIGURATION_BUILD_DIR}/LMJHorizontalScrollText" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/NXFramework-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "${PODS_CONFIGURATION_BUILD_DIR}/Realm" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/Toast-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "${PODS_ROOT}/Realm/core" "${PODS_ROOT}/TXLiteAVSDK_Player/TXLiteAVSDK_Player/SDK" "${PODS_ROOT}/WechatOpenSDK-Swift/Vendor"
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/AliyunOSSiOS" "${PODS_CONFIGURATION_BUILD_DIR}/FDFullscreenPopGesture" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "${PODS_CONFIGURATION_BUILD_DIR}/LMJHorizontalScrollText" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "${PODS_CONFIGURATION_BUILD_DIR}/Realm" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/Toast-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "${PODS_ROOT}/Bugly" "${PODS_ROOT}/Realm/core" "${PODS_ROOT}/TXLiteAVSDK_Player/TXLiteAVSDK_Player/SDK" "${PODS_ROOT}/WechatOpenSDK-Swift/Vendor"
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
 HEADER_SEARCH_PATHS = $(inherited) "${PODS_XCFRAMEWORKS_BUILD_DIR}/realm-monorepo/Headers"
 OTHER_LDFLAGS = $(inherited) -all_load
@@ -15,3 +15,4 @@ PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
 SKIP_INSTALL = YES
 USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
 VALIDATE_WORKSPACE_SKIPPED_SDK_FRAMEWORKS = OpenGLES
+VALID_ARCHS = arm64 armv7

+ 2 - 1
Example/Pods/Target Support Files/BFFramework/BFFramework.release.xcconfig

@@ -1,7 +1,7 @@
 CLANG_MODULES_AUTOLINK = YES
 CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
 CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/BFFramework
-FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/AliyunOSSiOS" "${PODS_CONFIGURATION_BUILD_DIR}/FDFullscreenPopGesture" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "${PODS_CONFIGURATION_BUILD_DIR}/LMJHorizontalScrollText" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/NXFramework-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "${PODS_CONFIGURATION_BUILD_DIR}/Realm" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/Toast-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "${PODS_ROOT}/Realm/core" "${PODS_ROOT}/TXLiteAVSDK_Player/TXLiteAVSDK_Player/SDK" "${PODS_ROOT}/WechatOpenSDK-Swift/Vendor"
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/AliyunOSSiOS" "${PODS_CONFIGURATION_BUILD_DIR}/FDFullscreenPopGesture" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "${PODS_CONFIGURATION_BUILD_DIR}/LMJHorizontalScrollText" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "${PODS_CONFIGURATION_BUILD_DIR}/Realm" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/Toast-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "${PODS_ROOT}/Bugly" "${PODS_ROOT}/Realm/core" "${PODS_ROOT}/TXLiteAVSDK_Player/TXLiteAVSDK_Player/SDK" "${PODS_ROOT}/WechatOpenSDK-Swift/Vendor"
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
 HEADER_SEARCH_PATHS = $(inherited) "${PODS_XCFRAMEWORKS_BUILD_DIR}/realm-monorepo/Headers"
 OTHER_LDFLAGS = $(inherited) -all_load
@@ -15,3 +15,4 @@ PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
 SKIP_INSTALL = YES
 USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
 VALIDATE_WORKSPACE_SKIPPED_SDK_FRAMEWORKS = OpenGLES
+VALID_ARCHS = arm64 armv7

+ 1 - 1
Example/Pods/Target Support Files/BFFramework/ResourceBundle-BFFramework-BFFramework-Info.plist

@@ -13,7 +13,7 @@
   <key>CFBundlePackageType</key>
   <string>BNDL</string>
   <key>CFBundleShortVersionString</key>
-  <string>0.1.0</string>
+  <string>0.1.1</string>
   <key>CFBundleSignature</key>
   <string>????</string>
   <key>CFBundleVersion</key>

+ 1 - 1
Example/Pods/Target Support Files/Kingfisher/Kingfisher-Info.plist

@@ -15,7 +15,7 @@
   <key>CFBundlePackageType</key>
   <string>FMWK</string>
   <key>CFBundleShortVersionString</key>
-  <string>4.10.1</string>
+  <string>6.3.0</string>
   <key>CFBundleSignature</key>
   <string>????</string>
   <key>CFBundleVersion</key>

+ 0 - 1
Example/Pods/Target Support Files/Kingfisher/Kingfisher-umbrella.h

@@ -10,7 +10,6 @@
 #endif
 #endif
 
-#import "Kingfisher.h"
 
 FOUNDATION_EXPORT double KingfisherVersionNumber;
 FOUNDATION_EXPORT const unsigned char KingfisherVersionString[];

+ 1 - 1
Example/Pods/Target Support Files/Kingfisher/Kingfisher.debug.xcconfig

@@ -1,7 +1,7 @@
 CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
 CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-OTHER_LDFLAGS = $(inherited) -framework "CFNetwork"
+OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -weak_framework "Combine" -weak_framework "SwiftUI"
 OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
 PODS_BUILD_DIR = ${BUILD_DIR}
 PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

+ 1 - 1
Example/Pods/Target Support Files/Kingfisher/Kingfisher.release.xcconfig

@@ -1,7 +1,7 @@
 CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
 CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-OTHER_LDFLAGS = $(inherited) -framework "CFNetwork"
+OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -weak_framework "Combine" -weak_framework "SwiftUI"
 OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
 PODS_BUILD_DIR = ${BUILD_DIR}
 PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

+ 0 - 26
Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift-Info.plist

@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-  <key>CFBundleDevelopmentRegion</key>
-  <string>en</string>
-  <key>CFBundleExecutable</key>
-  <string>${EXECUTABLE_NAME}</string>
-  <key>CFBundleIdentifier</key>
-  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
-  <key>CFBundleInfoDictionaryVersion</key>
-  <string>6.0</string>
-  <key>CFBundleName</key>
-  <string>${PRODUCT_NAME}</string>
-  <key>CFBundlePackageType</key>
-  <string>FMWK</string>
-  <key>CFBundleShortVersionString</key>
-  <string>0.1.0</string>
-  <key>CFBundleSignature</key>
-  <string>????</string>
-  <key>CFBundleVersion</key>
-  <string>${CURRENT_PROJECT_VERSION}</string>
-  <key>NSPrincipalClass</key>
-  <string></string>
-</dict>
-</plist>

+ 0 - 5
Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift-dummy.m

@@ -1,5 +0,0 @@
-#import <Foundation/Foundation.h>
-@interface PodsDummy_NXFramework_Swift : NSObject
-@end
-@implementation PodsDummy_NXFramework_Swift
-@end

+ 0 - 12
Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift-prefix.pch

@@ -1,12 +0,0 @@
-#ifdef __OBJC__
-#import <UIKit/UIKit.h>
-#else
-#ifndef FOUNDATION_EXPORT
-#if defined(__cplusplus)
-#define FOUNDATION_EXPORT extern "C"
-#else
-#define FOUNDATION_EXPORT extern
-#endif
-#endif
-#endif
-

+ 0 - 16
Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift-umbrella.h

@@ -1,16 +0,0 @@
-#ifdef __OBJC__
-#import <UIKit/UIKit.h>
-#else
-#ifndef FOUNDATION_EXPORT
-#if defined(__cplusplus)
-#define FOUNDATION_EXPORT extern "C"
-#else
-#define FOUNDATION_EXPORT extern
-#endif
-#endif
-#endif
-
-
-FOUNDATION_EXPORT double NXFramework_SwiftVersionNumber;
-FOUNDATION_EXPORT const unsigned char NXFramework_SwiftVersionString[];
-

+ 0 - 12
Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift.debug.xcconfig

@@ -1,12 +0,0 @@
-CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
-CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/NXFramework-Swift
-GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
-PODS_BUILD_DIR = ${BUILD_DIR}
-PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
-PODS_ROOT = ${SRCROOT}
-PODS_TARGET_SRCROOT = ${PODS_ROOT}/NXFramework-Swift
-PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
-PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
-SKIP_INSTALL = YES
-USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 0 - 6
Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift.modulemap

@@ -1,6 +0,0 @@
-framework module NXFramework_Swift {
-  umbrella header "NXFramework-Swift-umbrella.h"
-
-  export *
-  module * { export * }
-}

+ 0 - 12
Example/Pods/Target Support Files/NXFramework-Swift/NXFramework-Swift.release.xcconfig

@@ -1,12 +0,0 @@
-CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
-CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/NXFramework-Swift
-GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
-PODS_BUILD_DIR = ${BUILD_DIR}
-PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
-PODS_ROOT = ${SRCROOT}
-PODS_TARGET_SRCROOT = ${PODS_ROOT}/NXFramework-Swift
-PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
-PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
-SKIP_INSTALL = YES
-USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 6 - 24
Example/Pods/Target Support Files/Pods-BFFramework_Example/Pods-BFFramework_Example-acknowledgements.markdown

@@ -64,6 +64,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 
 
+## Bugly
+
+Copyright (C) 2017 Tencent Bugly, Inc. All rights reserved.
+
+
 ## FDFullscreenPopGesture
 
 The MIT License (MIT)
@@ -120,7 +125,7 @@ SOFTWARE.
 
 The MIT License (MIT)
 
-Copyright (c) 2018 Wei Wang
+Copyright (c) 2019 Wei Wang
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -210,29 +215,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 
 
-## NXFramework-Swift
-
-Copyright (c) 2020 287971051@qq.com <287971051@qq.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.
-
-
 ## ObjectMapper
 
 The MIT License (MIT)

+ 12 - 30
Example/Pods/Target Support Files/Pods-BFFramework_Example/Pods-BFFramework_Example-acknowledgements.plist

@@ -93,6 +93,17 @@ THE SOFTWARE.
 			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>Copyright (C) 2017 Tencent Bugly, Inc. All rights reserved.
+</string>
+			<key>License</key>
+			<string>Copyright</string>
+			<key>Title</key>
+			<string>Bugly</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
 		<dict>
 			<key>FooterText</key>
 			<string>The MIT License (MIT)
@@ -161,7 +172,7 @@ SOFTWARE.
 			<key>FooterText</key>
 			<string>The MIT License (MIT)
 
-Copyright (c) 2018 Wei Wang
+Copyright (c) 2019 Wei Wang
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -275,35 +286,6 @@ THE SOFTWARE.
 			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 		</dict>
-		<dict>
-			<key>FooterText</key>
-			<string>Copyright (c) 2020 287971051@qq.com &lt;287971051@qq.com&gt;
-
-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.
-</string>
-			<key>License</key>
-			<string>MIT</string>
-			<key>Title</key>
-			<string>NXFramework-Swift</string>
-			<key>Type</key>
-			<string>PSGroupSpecifier</string>
-		</dict>
 		<dict>
 			<key>FooterText</key>
 			<string>The MIT License (MIT)

+ 0 - 2
Example/Pods/Target Support Files/Pods-BFFramework_Example/Pods-BFFramework_Example-frameworks.sh

@@ -183,7 +183,6 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
   install_framework "${BUILT_PRODUCTS_DIR}/KingfisherWebP/KingfisherWebP.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/LMJHorizontalScrollText/LMJHorizontalScrollText.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework"
-  install_framework "${BUILT_PRODUCTS_DIR}/NXFramework-Swift/NXFramework_Swift.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/ObjectMapper/ObjectMapper.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/Realm/Realm.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/RealmSwift/RealmSwift.framework"
@@ -200,7 +199,6 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
   install_framework "${BUILT_PRODUCTS_DIR}/KingfisherWebP/KingfisherWebP.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/LMJHorizontalScrollText/LMJHorizontalScrollText.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework"
-  install_framework "${BUILT_PRODUCTS_DIR}/NXFramework-Swift/NXFramework_Swift.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/ObjectMapper/ObjectMapper.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/Realm/Realm.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/RealmSwift/RealmSwift.framework"

+ 3 - 4
Example/Pods/Target Support Files/Pods-BFFramework_Example/Pods-BFFramework_Example.debug.xcconfig

@@ -1,18 +1,17 @@
 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
 CLANG_MODULES_AUTOLINK = YES
 CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
-FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/AliyunOSSiOS" "${PODS_CONFIGURATION_BUILD_DIR}/BFFramework" "${PODS_CONFIGURATION_BUILD_DIR}/FDFullscreenPopGesture" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "${PODS_CONFIGURATION_BUILD_DIR}/LMJHorizontalScrollText" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/NXFramework-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "${PODS_CONFIGURATION_BUILD_DIR}/Realm" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/Toast-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "${PODS_ROOT}/Realm/core" "${PODS_ROOT}/TXLiteAVSDK_Player/TXLiteAVSDK_Player/SDK" "${PODS_ROOT}/WechatOpenSDK-Swift/Vendor"
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/AliyunOSSiOS" "${PODS_CONFIGURATION_BUILD_DIR}/BFFramework" "${PODS_CONFIGURATION_BUILD_DIR}/FDFullscreenPopGesture" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "${PODS_CONFIGURATION_BUILD_DIR}/LMJHorizontalScrollText" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "${PODS_CONFIGURATION_BUILD_DIR}/Realm" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/Toast-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "${PODS_ROOT}/Bugly" "${PODS_ROOT}/Realm/core" "${PODS_ROOT}/TXLiteAVSDK_Player/TXLiteAVSDK_Player/SDK" "${PODS_ROOT}/WechatOpenSDK-Swift/Vendor"
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/AliyunOSSiOS/AliyunOSSiOS.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BFFramework/BFFramework.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FDFullscreenPopGesture/FDFullscreenPopGesture.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP/KingfisherWebP.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LMJHorizontalScrollText/LMJHorizontalScrollText.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/NXFramework-Swift/NXFramework_Swift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper/ObjectMapper.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Realm/Realm.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift/RealmSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Toast-Swift/Toast_Swift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp/libwebp.framework/Headers" "${PODS_XCFRAMEWORKS_BUILD_DIR}/realm-monorepo/Headers" ${PODS_ROOT}/TXLiteAVSDK_Player/TXLiteAVSDK_Player/SDK/TXLiteAVSDK_Player.framework/Headers/
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/AliyunOSSiOS/AliyunOSSiOS.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BFFramework/BFFramework.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FDFullscreenPopGesture/FDFullscreenPopGesture.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP/KingfisherWebP.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LMJHorizontalScrollText/LMJHorizontalScrollText.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper/ObjectMapper.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Realm/Realm.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift/RealmSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Toast-Swift/Toast_Swift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp/libwebp.framework/Headers" "${PODS_XCFRAMEWORKS_BUILD_DIR}/realm-monorepo/Headers" ${PODS_ROOT}/TXLiteAVSDK_Player/TXLiteAVSDK_Player/SDK/TXLiteAVSDK_Player.framework/Headers/
 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
 LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_XCFRAMEWORKS_BUILD_DIR}/realm-monorepo"
-OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"iconv" -l"resolv" -l"sqlite3" -l"stdc++" -l"z" -framework "AVFoundation" -framework "Accelerate" -framework "Alamofire" -framework "AliyunOSSiOS" -framework "BFFramework" -framework "CFNetwork" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreTelephony" -framework "FDFullscreenPopGesture" -framework "KeychainAccess" -framework "Kingfisher" -framework "KingfisherWebP" -framework "LMJHorizontalScrollText" -framework "MJRefresh" -framework "NXFramework_Swift" -framework "ObjectMapper" -framework "OpenGLES" -framework "QuartzCore" -framework "Realm" -framework "RealmSwift" -framework "Security" -framework "SnapKit" -framework "SystemConfiguration" -framework "TXLiteAVSDK_Player" -framework "Toast_Swift" -framework "UIKit" -framework "VideoToolbox" -framework "WebKit" -framework "WechatOpenSDK" -framework "libwebp"
+OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"iconv" -l"resolv" -l"sqlite3" -l"stdc++" -l"z" -framework "AVFoundation" -framework "Accelerate" -framework "Alamofire" -framework "AliyunOSSiOS" -framework "BFFramework" -framework "Bugly" -framework "CFNetwork" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreTelephony" -framework "FDFullscreenPopGesture" -framework "KeychainAccess" -framework "Kingfisher" -framework "KingfisherWebP" -framework "LMJHorizontalScrollText" -framework "MJRefresh" -framework "ObjectMapper" -framework "OpenGLES" -framework "QuartzCore" -framework "Realm" -framework "RealmSwift" -framework "Security" -framework "SnapKit" -framework "SystemConfiguration" -framework "TXLiteAVSDK_Player" -framework "Toast_Swift" -framework "UIKit" -framework "VideoToolbox" -framework "WebKit" -framework "WechatOpenSDK" -framework "libwebp" -weak_framework "Combine" -weak_framework "SwiftUI"
 OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS $(inherited) -DGLES
 PODS_BUILD_DIR = ${BUILD_DIR}
 PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
 PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
 PODS_ROOT = ${SRCROOT}/Pods
 PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
-USER_HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/libwebp/src
 USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
 VALIDATE_WORKSPACE_SKIPPED_SDK_FRAMEWORKS = OpenGLES

+ 3 - 4
Example/Pods/Target Support Files/Pods-BFFramework_Example/Pods-BFFramework_Example.release.xcconfig

@@ -1,18 +1,17 @@
 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
 CLANG_MODULES_AUTOLINK = YES
 CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
-FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/AliyunOSSiOS" "${PODS_CONFIGURATION_BUILD_DIR}/BFFramework" "${PODS_CONFIGURATION_BUILD_DIR}/FDFullscreenPopGesture" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "${PODS_CONFIGURATION_BUILD_DIR}/LMJHorizontalScrollText" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/NXFramework-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "${PODS_CONFIGURATION_BUILD_DIR}/Realm" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/Toast-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "${PODS_ROOT}/Realm/core" "${PODS_ROOT}/TXLiteAVSDK_Player/TXLiteAVSDK_Player/SDK" "${PODS_ROOT}/WechatOpenSDK-Swift/Vendor"
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire" "${PODS_CONFIGURATION_BUILD_DIR}/AliyunOSSiOS" "${PODS_CONFIGURATION_BUILD_DIR}/BFFramework" "${PODS_CONFIGURATION_BUILD_DIR}/FDFullscreenPopGesture" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP" "${PODS_CONFIGURATION_BUILD_DIR}/LMJHorizontalScrollText" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper" "${PODS_CONFIGURATION_BUILD_DIR}/Realm" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit" "${PODS_CONFIGURATION_BUILD_DIR}/Toast-Swift" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp" "${PODS_ROOT}/Bugly" "${PODS_ROOT}/Realm/core" "${PODS_ROOT}/TXLiteAVSDK_Player/TXLiteAVSDK_Player/SDK" "${PODS_ROOT}/WechatOpenSDK-Swift/Vendor"
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/AliyunOSSiOS/AliyunOSSiOS.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BFFramework/BFFramework.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FDFullscreenPopGesture/FDFullscreenPopGesture.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP/KingfisherWebP.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LMJHorizontalScrollText/LMJHorizontalScrollText.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/NXFramework-Swift/NXFramework_Swift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper/ObjectMapper.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Realm/Realm.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift/RealmSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Toast-Swift/Toast_Swift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp/libwebp.framework/Headers" "${PODS_XCFRAMEWORKS_BUILD_DIR}/realm-monorepo/Headers" ${PODS_ROOT}/TXLiteAVSDK_Player/TXLiteAVSDK_Player/SDK/TXLiteAVSDK_Player.framework/Headers/
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Alamofire/Alamofire.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/AliyunOSSiOS/AliyunOSSiOS.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/BFFramework/BFFramework.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FDFullscreenPopGesture/FDFullscreenPopGesture.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KeychainAccess/KeychainAccess.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/KingfisherWebP/KingfisherWebP.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LMJHorizontalScrollText/LMJHorizontalScrollText.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ObjectMapper/ObjectMapper.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Realm/Realm.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/RealmSwift/RealmSwift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Toast-Swift/Toast_Swift.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/libwebp/libwebp.framework/Headers" "${PODS_XCFRAMEWORKS_BUILD_DIR}/realm-monorepo/Headers" ${PODS_ROOT}/TXLiteAVSDK_Player/TXLiteAVSDK_Player/SDK/TXLiteAVSDK_Player.framework/Headers/
 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
 LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_XCFRAMEWORKS_BUILD_DIR}/realm-monorepo"
-OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"iconv" -l"resolv" -l"sqlite3" -l"stdc++" -l"z" -framework "AVFoundation" -framework "Accelerate" -framework "Alamofire" -framework "AliyunOSSiOS" -framework "BFFramework" -framework "CFNetwork" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreTelephony" -framework "FDFullscreenPopGesture" -framework "KeychainAccess" -framework "Kingfisher" -framework "KingfisherWebP" -framework "LMJHorizontalScrollText" -framework "MJRefresh" -framework "NXFramework_Swift" -framework "ObjectMapper" -framework "OpenGLES" -framework "QuartzCore" -framework "Realm" -framework "RealmSwift" -framework "Security" -framework "SnapKit" -framework "SystemConfiguration" -framework "TXLiteAVSDK_Player" -framework "Toast_Swift" -framework "UIKit" -framework "VideoToolbox" -framework "WebKit" -framework "WechatOpenSDK" -framework "libwebp"
+OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"iconv" -l"resolv" -l"sqlite3" -l"stdc++" -l"z" -framework "AVFoundation" -framework "Accelerate" -framework "Alamofire" -framework "AliyunOSSiOS" -framework "BFFramework" -framework "Bugly" -framework "CFNetwork" -framework "CoreGraphics" -framework "CoreMedia" -framework "CoreTelephony" -framework "FDFullscreenPopGesture" -framework "KeychainAccess" -framework "Kingfisher" -framework "KingfisherWebP" -framework "LMJHorizontalScrollText" -framework "MJRefresh" -framework "ObjectMapper" -framework "OpenGLES" -framework "QuartzCore" -framework "Realm" -framework "RealmSwift" -framework "Security" -framework "SnapKit" -framework "SystemConfiguration" -framework "TXLiteAVSDK_Player" -framework "Toast_Swift" -framework "UIKit" -framework "VideoToolbox" -framework "WebKit" -framework "WechatOpenSDK" -framework "libwebp" -weak_framework "Combine" -weak_framework "SwiftUI"
 OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS $(inherited) -DGLES
 PODS_BUILD_DIR = ${BUILD_DIR}
 PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
 PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
 PODS_ROOT = ${SRCROOT}/Pods
 PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
-USER_HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/libwebp/src
 USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
 VALIDATE_WORKSPACE_SKIPPED_SDK_FRAMEWORKS = OpenGLES

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels