diff --git a/.gitIgnore b/.gitIgnore
deleted file mode 100644
index 312d1f6..0000000
--- a/.gitIgnore
+++ /dev/null
@@ -1,68 +0,0 @@
-# Xcode
-#
-# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
-
-## Build generated
-build/
-DerivedData/
-
-## Various settings
-*.pbxuser
-!default.pbxuser
-*.mode1v3
-!default.mode1v3
-*.mode2v3
-!default.mode2v3
-*.perspectivev3
-!default.perspectivev3
-xcuserdata/
-
-## Other
-*.moved-aside
-*.xccheckout
-*.xcscmblueprint
-
-## Obj-C/Swift specific
-*.hmap
-*.ipa
-*.dSYM.zip
-*.dSYM
-
-## Playgrounds
-timeline.xctimeline
-playground.xcworkspace
-
-# Swift Package Manager
-#
-# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
-# Packages/
-# Package.pins
-# Package.resolved
-.build/
-
-# CocoaPods
-#
-# We recommend against adding the Pods directory to your .gitignore. However
-# you should judge for yourself, the pros and cons are mentioned at:
-# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
-#
-# Pods/
-
-# Carthage
-#
-# Add this line if you want to avoid checking in source code from Carthage dependencies.
-# Carthage/Checkouts
-
-Carthage/Build
-
-# fastlane
-#
-# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
-# screenshots whenever they are needed.
-# For more information about the recommended setup visit:
-# https://docs.fastlane.tools/best-practices/source-control/#source-control
-
-fastlane/report.xml
-fastlane/Preview.html
-fastlane/screenshots/**/*.png
-fastlane/test_output
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5cec1cb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,133 @@
+
+# Created by https://www.toptal.com/developers/gitignore/api/xcode,cocoapods,swift,fastlane
+# Edit at https://www.toptal.com/developers/gitignore?templates=xcode,cocoapods,swift,fastlane
+
+### CocoaPods ###
+## CocoaPods GitIgnore Template
+
+# CocoaPods - Only use to conserve bandwidth / Save time on Pushing
+# - Also handy if you have a large number of dependant pods
+# - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE
+Pods/
+
+### fastlane ###
+# fastlane - A streamlined workflow tool for Cocoa deployment
+#
+# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
+# screenshots whenever they are needed.
+# For more information about the recommended setup visit:
+# https://docs.fastlane.tools/best-practices/source-control/#source-control
+
+# fastlane specific
+fastlane/report.xml
+
+# deliver temporary files
+fastlane/Preview.html
+
+# snapshot generated screenshots
+fastlane/screenshots/**/*.png
+fastlane/screenshots/screenshots.html
+
+# scan temporary files
+fastlane/test_output
+
+# Fastlane.swift runner binary
+fastlane/FastlaneRunner
+
+### Swift ###
+# Xcode
+# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
+
+## User settings
+xcuserdata/
+
+## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
+*.xcscmblueprint
+*.xccheckout
+
+## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
+build/
+DerivedData/
+*.moved-aside
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+
+## Obj-C/Swift specific
+*.hmap
+
+## App packaging
+*.ipa
+*.dSYM.zip
+*.dSYM
+
+## Playgrounds
+timeline.xctimeline
+playground.xcworkspace
+
+# Swift Package Manager
+# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
+# Packages/
+# Package.pins
+# Package.resolved
+# *.xcodeproj
+# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
+# hence it is not needed unless you have added a package configuration file to your project
+# .swiftpm
+
+.build/
+
+# CocoaPods
+# We recommend against adding the Pods directory to your .gitignore. However
+# you should judge for yourself, the pros and cons are mentioned at:
+# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
+# Pods/
+# Add this line if you want to avoid checking in source code from the Xcode workspace
+# *.xcworkspace
+
+# Carthage
+# Add this line if you want to avoid checking in source code from Carthage dependencies.
+# Carthage/Checkouts
+
+Carthage/Build/
+
+# Add this lines if you are using Accio dependency management (Deprecated since Xcode 12)
+# Dependencies/
+# .accio/
+
+# fastlane
+# It is recommended to not store the screenshots in the git repo.
+# Instead, use fastlane to re-generate the screenshots whenever they are needed.
+# For more information about the recommended setup visit:
+# https://docs.fastlane.tools/best-practices/source-control/#source-control
+
+
+# Code Injection
+# After new code Injection tools there's a generated folder /iOSInjectionProject
+# https://github.com/johnno1962/injectionforxcode
+
+iOSInjectionProject/
+
+### Xcode ###
+# Xcode
+# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
+
+
+
+
+## Gcc Patch
+/*.gcno
+
+### Xcode Patch ###
+*.xcodeproj/*
+!*.xcodeproj/project.pbxproj
+!*.xcodeproj/xcshareddata/
+!*.xcworkspace/contents.xcworkspacedata
+**/xcshareddata/WorkspaceSettings.xcsettings
+
+# End of https://www.toptal.com/developers/gitignore/api/xcode,cocoapods,swift,fastlane
diff --git "a/BringMyOwnBeer\360\237\215\272.xcodeproj/project.xcworkspace/contents.xcworkspacedata" "b/BringMyOwnBeer\360\237\215\272.xcodeproj/project.xcworkspace/contents.xcworkspacedata"
deleted file mode 100644
index 0e652b9..0000000
--- "a/BringMyOwnBeer\360\237\215\272.xcodeproj/project.xcworkspace/contents.xcworkspacedata"
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git "a/BringMyOwnBeer\360\237\215\272.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist" "b/BringMyOwnBeer\360\237\215\272.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist"
deleted file mode 100644
index 18d9810..0000000
--- "a/BringMyOwnBeer\360\237\215\272.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist"
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEDidComputeMac32BitWarning
-
-
-
diff --git "a/BringMyOwnBeer\360\237\215\272.xcodeproj/project.xcworkspace/xcuserdata/boyoung.xcuserdatad/UserInterfaceState.xcuserstate" "b/BringMyOwnBeer\360\237\215\272.xcodeproj/project.xcworkspace/xcuserdata/boyoung.xcuserdatad/UserInterfaceState.xcuserstate"
deleted file mode 100644
index 7c1f3c7..0000000
Binary files "a/BringMyOwnBeer\360\237\215\272.xcodeproj/project.xcworkspace/xcuserdata/boyoung.xcuserdatad/UserInterfaceState.xcuserstate" and /dev/null differ
diff --git "a/BringMyOwnBeer\360\237\215\272.xcodeproj/xcuserdata/boyoung.xcuserdatad/xcschemes/xcschememanagement.plist" "b/BringMyOwnBeer\360\237\215\272.xcodeproj/xcuserdata/boyoung.xcuserdatad/xcschemes/xcschememanagement.plist"
deleted file mode 100644
index d8a2ee1..0000000
--- "a/BringMyOwnBeer\360\237\215\272.xcodeproj/xcuserdata/boyoung.xcuserdatad/xcschemes/xcschememanagement.plist"
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
- SchemeUserState
-
- BringMyOwnBeer🍺.xcscheme_^#shared#^_
-
- orderHint
- 22
-
-
-
-
diff --git "a/BringMyOwnBeer\360\237\215\272.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings" "b/BringMyOwnBeer\360\237\215\272.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings"
deleted file mode 100644
index 949b678..0000000
--- "a/BringMyOwnBeer\360\237\215\272.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings"
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- BuildSystemType
- Original
-
-
diff --git "a/BringMyOwnBeer\360\237\215\272.xcworkspace/xcuserdata/boyoung.xcuserdatad/UserInterfaceState.xcuserstate" "b/BringMyOwnBeer\360\237\215\272.xcworkspace/xcuserdata/boyoung.xcuserdatad/UserInterfaceState.xcuserstate"
deleted file mode 100644
index be6d93d..0000000
Binary files "a/BringMyOwnBeer\360\237\215\272.xcworkspace/xcuserdata/boyoung.xcuserdatad/UserInterfaceState.xcuserstate" and /dev/null differ
diff --git "a/BringMyOwnBeer\360\237\215\272.xcworkspace/xcuserdata/boyoung.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist" "b/BringMyOwnBeer\360\237\215\272.xcworkspace/xcuserdata/boyoung.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist"
deleted file mode 100644
index ed9a9b4..0000000
--- "a/BringMyOwnBeer\360\237\215\272.xcworkspace/xcuserdata/boyoung.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist"
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/Pods/Differentiator/LICENSE.md b/Pods/Differentiator/LICENSE.md
deleted file mode 100644
index 6705bea..0000000
--- a/Pods/Differentiator/LICENSE.md
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2017 RxSwift Community
-
-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.
diff --git a/Pods/Differentiator/README.md b/Pods/Differentiator/README.md
deleted file mode 100644
index 88891b6..0000000
--- a/Pods/Differentiator/README.md
+++ /dev/null
@@ -1,169 +0,0 @@
-[![Travis CI](https://travis-ci.org/RxSwiftCommunity/RxDataSources.svg?branch=master)](https://travis-ci.org/RxSwiftCommunity/RxDataSources)
-
-Table and Collection view data sources
-======================================
-
-## Features
-
-- [x] **O(N)** algorithm for calculating differences
- - the algorithm has the assumption that all sections and items are unique so there is no ambiguity
- - in case there is ambiguity, fallbacks automagically on non animated refresh
-- [x] it applies additional heuristics to send the least number of commands to sectioned view
- - even though the running time is linear, preferred number of sent commands is usually a lot less than linear
- - it is preferred (and possible) to cap the number of changes to some small number, and in case the number of changes grows towards linear, just do normal reload
-- [x] Supports **extending your item and section structures**
- - just extend your item with `IdentifiableType` and `Equatable`, and your section with `AnimatableSectionModelType`
-- [x] Supports all combinations of two level hierarchical animations for **both sections and items**
- - Section animations: Insert, Delete, Move
- - Item animations: Insert, Delete, Move, Reload (if old value is not equal to new value)
-- [x] Configurable animation types for `Insert`, `Reload` and `Delete` (Automatic, Fade, ...)
-- [x] Example app
-- [x] Randomized stress tests (example app)
-- [x] Supports editing out of the box (example app)
-- [x] Works with `UITableView` and `UICollectionView`
-
-## Why
-Writing table and collection view data sources is tedious. There is a large number of delegate methods that need to be implemented for the simplest case possible.
-
-RxSwift helps alleviate some of the burden with a simple data binding mechanism:
-1) Turn your data into an Observable sequence
-2) Bind the data to the tableView/collectionView using one of:
- - `rx.items(dataSource:protocol)`
- - `rx.items(cellIdentifier:String)`
- - `rx.items(cellIdentifier:String:Cell.Type:_:)`
- - `rx.items(_:_:)`
-
-```swift
-let data = Observable<[String]>.just(["first element", "second element", "third element"])
-
-data.bind(to: tableView.rx.items(cellIdentifier: "Cell")) { index, model, cell in
- cell.textLabel?.text = model
-}
-.disposed(by: disposeBag)
-```
-
-This works well with simple data sets but does not handle cases where you need to bind complex data sets with multiples sections, or when you need to perform animations when adding/modifying/deleting items.
-
-These are precisely the use cases that RxDataSources helps solve.
-
-With RxDataSources, it is super easy to just write
-
-```swift
-let dataSource = RxTableViewSectionedReloadDataSource>(configureCell: configureCell)
-Observable.just([SectionModel(model: "title", items: [1, 2, 3])])
- .bind(to: tableView.rx.items(dataSource: dataSource))
- .disposed(by: disposeBag)
-```
-![RxDataSources example app](https://raw.githubusercontent.com/kzaher/rxswiftcontent/rxdatasources/RxDataSources.gif)
-
-## How
-Given the following custom data structure:
-```swift
-struct CustomData {
- var anInt: Int
- var aString: String
- var aCGPoint: CGPoint
-}
-```
-
-1) Start by defining your sections with a struct that conforms to the `SectionModelType` protocol:
- - define the `Item` typealias: equal to the type of items that the section will contain
- - declare an `items` property: of type array of `Item`
-
-```swift
-struct SectionOfCustomData {
- var header: String
- var items: [Item]
-}
-extension SectionOfCustomData: SectionModelType {
- typealias Item = CustomData
-
- init(original: SectionOfCustomData, items: [Item]) {
- self = original
- self.items = items
- }
-}
-```
-
-2) Create a dataSource object and pass it your `SectionOfCustomData` type:
-```swift
-let dataSource = RxTableViewSectionedReloadDataSource(
- configureCell: { dataSource, tableView, indexPath, item in
- let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
- cell.textLabel?.text = "Item \(item.anInt): \(item.aString) - \(item.aCGPoint.x):\(item.aCGPoint.y)"
- return cell
-})
-```
-
-3) Customize closures on the dataSource as needed:
-- `titleForHeaderInSection`
-- `titleForFooterInSection`
-- etc
-
-```swift
-dataSource.titleForHeaderInSection = { dataSource, index in
- return dataSource.sectionModels[index].header
-}
-
-dataSource.titleForFooterInSection = { dataSource, indexPath in
- return dataSource.sectionModels[index].footer
-}
-
-dataSource.canEditRowAtIndexPath = { dataSource, indexPath in
- return true
-}
-
-dataSource.canMoveRowAtIndexPath = { dataSource, indexPath in
- return true
-}
-```
-
-4) Define the actual data as an Observable sequence of CustomData objects and bind it to the tableView
-```swift
-let sections = [
- SectionOfCustomData(header: "First section", items: [CustomData(anInt: 0, aString: "zero", aCGPoint: CGPoint.zero), CustomData(anInt: 1, aString: "one", aCGPoint: CGPoint(x: 1, y: 1)) ]),
- SectionOfCustomData(header: "Second section", items: [CustomData(anInt: 2, aString: "two", aCGPoint: CGPoint(x: 2, y: 2)), CustomData(anInt: 3, aString: "three", aCGPoint: CGPoint(x: 3, y: 3)) ])
-]
-
-Observable.just(sections)
- .bind(to: tableView.rx.items(dataSource: dataSource))
- .disposed(by: disposeBag)
-```
-
-### Animated Data Sources
-
-RxDataSources provides two special data source types that automatically take care of animating changes in the bound data source: `RxTableViewSectionedAnimatedDataSource` and `RxCollectionViewSectionedAnimatedDataSource`.
-
-To use one of the two animated data sources, you must take a few extra steps on top of those outlined above:
-
-- SectionOfCustomData needs to conform to `AnimatableSectionModelType`
-- Your data model must conform to
- * `IdentifiableType`: The `identity` provided by the `IdentifiableType` protocol must be an **immutable identifier representing an instance of the model**. For example, in case of a `Car` model, you might want to use the car's `plateNumber` as its identity.
- * `Equatable`: Conforming to `Equatable` helps `RxDataSources` determine which cells have changed so it can animate only these specific cells. Meaning, changing **any** of the `Car` model's properties will trigger an animated reload of that cell.
-
-## Requirements
-
-Xcode 9.0
-
-Swift 4.0
-
-For Swift 3.x version please use versions `1.0 ... 2.0.2`
-For Swift 2.3 version please use versions `0.1 ... 0.9`
-
-## Installation
-
-**We'll try to keep the API as stable as possible, but breaking API changes can occur.**
-
-### CocoaPods
-
-Podfile
-```
-pod 'RxDataSources', '~> 3.0'
-```
-
-### Carthage
-
-Cartfile
-```
-github "RxSwiftCommunity/RxDataSources" ~> 3.0
-```
diff --git a/Pods/Differentiator/Sources/Differentiator/AnimatableSectionModel.swift b/Pods/Differentiator/Sources/Differentiator/AnimatableSectionModel.swift
deleted file mode 100644
index 8141a62..0000000
--- a/Pods/Differentiator/Sources/Differentiator/AnimatableSectionModel.swift
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// AnimatableSectionModel.swift
-// RxDataSources
-//
-// Created by Krunoslav Zaher on 1/10/16.
-// Copyright © 2016 Krunoslav Zaher. All rights reserved.
-//
-
-import Foundation
-
-public struct AnimatableSectionModel {
- public var model: Section
- public var items: [Item]
-
- public init(model: Section, items: [ItemType]) {
- self.model = model
- self.items = items
- }
-
-}
-
-extension AnimatableSectionModel
- : AnimatableSectionModelType {
- public typealias Item = ItemType
- public typealias Identity = Section.Identity
-
- public var identity: Section.Identity {
- return model.identity
- }
-
- public init(original: AnimatableSectionModel, items: [Item]) {
- self.model = original.model
- self.items = items
- }
-
- public var hashValue: Int {
- return self.model.identity.hashValue
- }
-}
-
-
-extension AnimatableSectionModel
- : CustomStringConvertible {
-
- public var description: String {
- return "HashableSectionModel(model: \"\(self.model)\", items: \(items))"
- }
-
-}
diff --git a/Pods/Differentiator/Sources/Differentiator/AnimatableSectionModelType+ItemPath.swift b/Pods/Differentiator/Sources/Differentiator/AnimatableSectionModelType+ItemPath.swift
deleted file mode 100644
index 8a2b862..0000000
--- a/Pods/Differentiator/Sources/Differentiator/AnimatableSectionModelType+ItemPath.swift
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-// AnimatableSectionModelType+ItemPath.swift
-// RxDataSources
-//
-// Created by Krunoslav Zaher on 1/9/16.
-// Copyright © 2016 Krunoslav Zaher. All rights reserved.
-//
-
-import Foundation
-
-extension Array where Element: AnimatableSectionModelType {
- subscript(index: ItemPath) -> Element.Item {
- return self[index.sectionIndex].items[index.itemIndex]
- }
-}
\ No newline at end of file
diff --git a/Pods/Differentiator/Sources/Differentiator/AnimatableSectionModelType.swift b/Pods/Differentiator/Sources/Differentiator/AnimatableSectionModelType.swift
deleted file mode 100644
index 53e6e5c..0000000
--- a/Pods/Differentiator/Sources/Differentiator/AnimatableSectionModelType.swift
+++ /dev/null
@@ -1,14 +0,0 @@
-//
-// AnimatableSectionModelType.swift
-// RxDataSources
-//
-// Created by Krunoslav Zaher on 1/6/16.
-// Copyright © 2016 Krunoslav Zaher. All rights reserved.
-//
-
-import Foundation
-
-public protocol AnimatableSectionModelType
- : SectionModelType
- , IdentifiableType where Item: IdentifiableType, Item: Equatable {
-}
diff --git a/Pods/Differentiator/Sources/Differentiator/Changeset.swift b/Pods/Differentiator/Sources/Differentiator/Changeset.swift
deleted file mode 100644
index b3e88a3..0000000
--- a/Pods/Differentiator/Sources/Differentiator/Changeset.swift
+++ /dev/null
@@ -1,92 +0,0 @@
-//
-// Changeset.swift
-// RxDataSources
-//
-// Created by Krunoslav Zaher on 5/30/15.
-// Copyright © 2015 Krunoslav Zaher. All rights reserved.
-//
-
-import Foundation
-
-public struct Changeset {
- public typealias I = S.Item
-
- public let reloadData: Bool
-
- public let originalSections: [S]
- public let finalSections: [S]
-
- public let insertedSections: [Int]
- public let deletedSections: [Int]
- public let movedSections: [(from: Int, to: Int)]
- public let updatedSections: [Int]
-
- public let insertedItems: [ItemPath]
- public let deletedItems: [ItemPath]
- public let movedItems: [(from: ItemPath, to: ItemPath)]
- public let updatedItems: [ItemPath]
-
- init(reloadData: Bool = false,
- originalSections: [S] = [],
- finalSections: [S] = [],
- insertedSections: [Int] = [],
- deletedSections: [Int] = [],
- movedSections: [(from: Int, to: Int)] = [],
- updatedSections: [Int] = [],
-
- insertedItems: [ItemPath] = [],
- deletedItems: [ItemPath] = [],
- movedItems: [(from: ItemPath, to: ItemPath)] = [],
- updatedItems: [ItemPath] = []
- ) {
- self.reloadData = reloadData
-
- self.originalSections = originalSections
- self.finalSections = finalSections
-
- self.insertedSections = insertedSections
- self.deletedSections = deletedSections
- self.movedSections = movedSections
- self.updatedSections = updatedSections
-
- self.insertedItems = insertedItems
- self.deletedItems = deletedItems
- self.movedItems = movedItems
- self.updatedItems = updatedItems
- }
-
- public static func initialValue(_ sections: [S]) -> Changeset {
- return Changeset(
- reloadData: true,
- finalSections: sections,
- insertedSections: Array(0 ..< sections.count) as [Int]
- )
- }
-}
-
-extension ItemPath
- : CustomDebugStringConvertible {
- public var debugDescription : String {
- return "(\(sectionIndex), \(itemIndex))"
- }
-}
-
-extension Changeset
- : CustomDebugStringConvertible {
-
- public var debugDescription : String {
- let serializedSections = "[\n" + finalSections.map { "\($0)" }.joined(separator: ",\n") + "\n]\n"
- return " >> Final sections"
- + " \n\(serializedSections)"
- + (!insertedSections.isEmpty || !deletedSections.isEmpty || !movedSections.isEmpty || !updatedSections.isEmpty ? "\nSections:" : "")
- + (!insertedSections.isEmpty ? "\ninsertedSections:\n\t\(insertedSections)" : "")
- + (!deletedSections.isEmpty ? "\ndeletedSections:\n\t\(deletedSections)" : "")
- + (!movedSections.isEmpty ? "\nmovedSections:\n\t\(movedSections)" : "")
- + (!updatedSections.isEmpty ? "\nupdatesSections:\n\t\(updatedSections)" : "")
- + (!insertedItems.isEmpty || !deletedItems.isEmpty || !movedItems.isEmpty || !updatedItems.isEmpty ? "\nItems:" : "")
- + (!insertedItems.isEmpty ? "\ninsertedItems:\n\t\(insertedItems)" : "")
- + (!deletedItems.isEmpty ? "\ndeletedItems:\n\t\(deletedItems)" : "")
- + (!movedItems.isEmpty ? "\nmovedItems:\n\t\(movedItems)" : "")
- + (!updatedItems.isEmpty ? "\nupdatedItems:\n\t\(updatedItems)" : "")
- }
-}
diff --git a/Pods/Differentiator/Sources/Differentiator/Diff.swift b/Pods/Differentiator/Sources/Differentiator/Diff.swift
deleted file mode 100644
index b1ff394..0000000
--- a/Pods/Differentiator/Sources/Differentiator/Diff.swift
+++ /dev/null
@@ -1,793 +0,0 @@
-//
-// Differentiator.swift
-// RxDataSources
-//
-// Created by Krunoslav Zaher on 6/27/15.
-// Copyright © 2015 Krunoslav Zaher. All rights reserved.
-//
-
-import Foundation
-
-fileprivate extension AnimatableSectionModelType {
- init(safeOriginal: Self, safeItems: [Item]) throws {
- self.init(original: safeOriginal, items: safeItems)
-
- if self.items != safeItems || self.identity != safeOriginal.identity {
- throw Diff.Error.invalidInitializerImplementation(section: self, expectedItems: safeItems, expectedIdentifier: safeOriginal.identity)
- }
- }
-}
-
-public enum Diff {
-
- public enum Error : Swift.Error, CustomDebugStringConvertible {
-
- case duplicateItem(item: Any)
- case duplicateSection(section: Any)
- case invalidInitializerImplementation(section: Any, expectedItems: Any, expectedIdentifier: Any)
-
- public var debugDescription: String {
- switch self {
- case let .duplicateItem(item):
- return "Duplicate item \(item)"
- case let .duplicateSection(section):
- return "Duplicate section \(section)"
- case let .invalidInitializerImplementation(section, expectedItems, expectedIdentifier):
- return "Wrong initializer implementation for: \(section)\n" +
- "Expected it should return items: \(expectedItems)\n" +
- "Expected it should have id: \(expectedIdentifier)"
- }
- }
- }
-
- private enum EditEvent : CustomDebugStringConvertible {
- case inserted // can't be found in old sections
- case insertedAutomatically // Item inside section being inserted
- case deleted // Was in old, not in new, in it's place is something "not new" :(, otherwise it's Updated
- case deletedAutomatically // Item inside section that is being deleted
- case moved // same item, but was on different index, and needs explicit move
- case movedAutomatically // don't need to specify any changes for those rows
- case untouched
-
- var debugDescription: String {
- get {
- switch self {
- case .inserted:
- return "Inserted"
- case .insertedAutomatically:
- return "InsertedAutomatically"
- case .deleted:
- return "Deleted"
- case .deletedAutomatically:
- return "DeletedAutomatically"
- case .moved:
- return "Moved"
- case .movedAutomatically:
- return "MovedAutomatically"
- case .untouched:
- return "Untouched"
- }
- }
- }
- }
-
- private struct SectionAssociatedData : CustomDebugStringConvertible {
- var event: EditEvent
- var indexAfterDelete: Int?
- var moveIndex: Int?
- var itemCount: Int
-
- var debugDescription: String {
- get {
- return "\(event), \(String(describing: indexAfterDelete))"
- }
- }
-
- static var initial: SectionAssociatedData {
- return SectionAssociatedData(event: .untouched, indexAfterDelete: nil, moveIndex: nil, itemCount: 0)
- }
- }
-
- private struct ItemAssociatedData: CustomDebugStringConvertible {
- var event: EditEvent
- var indexAfterDelete: Int?
- var moveIndex: ItemPath?
-
- var debugDescription: String {
- get {
- return "\(event) \(String(describing: indexAfterDelete))"
- }
- }
-
- static var initial : ItemAssociatedData {
- return ItemAssociatedData(event: .untouched, indexAfterDelete: nil, moveIndex: nil)
- }
- }
-
- private static func indexSections(_ sections: [S]) throws -> [S.Identity : Int] {
- var indexedSections: [S.Identity : Int] = [:]
- for (i, section) in sections.enumerated() {
- guard indexedSections[section.identity] == nil else {
- #if DEBUG
- if indexedSections[section.identity] != nil {
- print("Section \(section) has already been indexed at \(indexedSections[section.identity]!)")
- }
- #endif
- throw Error.duplicateSection(section: section)
- }
- indexedSections[section.identity] = i
- }
-
- return indexedSections
- }
-
- //================================================================================
- // Optimizations because Swift dictionaries are extremely slow (ARC, bridging ...)
- //================================================================================
- // swift dictionary optimizations {
-
- private struct OptimizedIdentity : Hashable {
-
- let hashValue: Int
- let identity: UnsafePointer
-
- init(_ identity: UnsafePointer) {
- self.identity = identity
- self.hashValue = identity.pointee.hashValue
- }
-
- static func == (lhs: OptimizedIdentity, rhs: OptimizedIdentity) -> Bool {
- if lhs.hashValue != rhs.hashValue {
- return false
- }
-
- if lhs.identity.distance(to: rhs.identity) == 0 {
- return true
- }
-
- return lhs.identity.pointee == rhs.identity.pointee
- }
-
- }
-
- private static func calculateAssociatedData(
- initialItemCache: ContiguousArray>,
- finalItemCache: ContiguousArray>
- ) throws
- -> (ContiguousArray>, ContiguousArray>) {
-
- typealias Identity = Item.Identity
- let totalInitialItems = initialItemCache.map { $0.count }.reduce(0, +)
-
- var initialIdentities: ContiguousArray = ContiguousArray()
- var initialItemPaths: ContiguousArray = ContiguousArray()
-
- initialIdentities.reserveCapacity(totalInitialItems)
- initialItemPaths.reserveCapacity(totalInitialItems)
-
- for (i, items) in initialItemCache.enumerated() {
- for j in 0 ..< items.count {
- let item = items[j]
- initialIdentities.append(item.identity)
- initialItemPaths.append(ItemPath(sectionIndex: i, itemIndex: j))
- }
- }
-
- var initialItemData = ContiguousArray(initialItemCache.map { items in
- return ContiguousArray(repeating: ItemAssociatedData.initial, count: items.count)
- })
-
- var finalItemData = ContiguousArray(finalItemCache.map { items in
- return ContiguousArray(repeating: ItemAssociatedData.initial, count: items.count)
- })
-
- try initialIdentities.withUnsafeBufferPointer { (identitiesBuffer: UnsafeBufferPointer) -> () in
- var dictionary: [OptimizedIdentity: Int] = Dictionary(minimumCapacity: totalInitialItems * 2)
-
- for i in 0 ..< initialIdentities.count {
- let identityPointer = identitiesBuffer.baseAddress!.advanced(by: i)
-
- let key = OptimizedIdentity(identityPointer)
-
- if let existingValueItemPathIndex = dictionary[key] {
- let itemPath = initialItemPaths[existingValueItemPathIndex]
- let item = initialItemCache[itemPath.sectionIndex][itemPath.itemIndex]
- #if DEBUG
- print("Item \(item) has already been indexed at \(itemPath)" )
- #endif
- throw Error.duplicateItem(item: item)
- }
-
- dictionary[key] = i
- }
-
- for (i, items) in finalItemCache.enumerated() {
- for j in 0 ..< items.count {
- let item = items[j]
- var identity = item.identity
- let key = OptimizedIdentity(&identity)
- guard let initialItemPathIndex = dictionary[key] else {
- continue
- }
- let itemPath = initialItemPaths[initialItemPathIndex]
- if initialItemData[itemPath.sectionIndex][itemPath.itemIndex].moveIndex != nil {
- throw Error.duplicateItem(item: item)
- }
-
- initialItemData[itemPath.sectionIndex][itemPath.itemIndex].moveIndex = ItemPath(sectionIndex: i, itemIndex: j)
- finalItemData[i][j].moveIndex = itemPath
- }
- }
-
- return ()
- }
-
- return (initialItemData, finalItemData)
- }
-
- // } swift dictionary optimizations
-
- /*
-
- I've uncovered this case during random stress testing of logic.
- This is the hardest generic update case that causes two passes, first delete, and then move/insert
-
- [
- NumberSection(model: "1", items: [1111]),
- NumberSection(model: "2", items: [2222]),
- ]
-
- [
- NumberSection(model: "2", items: [0]),
- NumberSection(model: "1", items: []),
- ]
-
- If update is in the form
-
- * Move section from 2 to 1
- * Delete Items at paths 0 - 0, 1 - 0
- * Insert Items at paths 0 - 0
-
- or
-
- * Move section from 2 to 1
- * Delete Items at paths 0 - 0
- * Reload Items at paths 1 - 0
-
- or
-
- * Move section from 2 to 1
- * Delete Items at paths 0 - 0
- * Reload Items at paths 0 - 0
-
- it crashes table view.
-
- No matter what change is performed, it fails for me.
- If anyone knows how to make this work for one Changeset, PR is welcome.
-
- */
-
- // If you are considering working out your own algorithm, these are tricky
- // transition cases that you can use.
-
- // case 1
- /*
- from = [
- NumberSection(model: "section 4", items: [10, 11, 12]),
- NumberSection(model: "section 9", items: [25, 26, 27]),
- ]
- to = [
- HashableSectionModel(model: "section 9", items: [11, 26, 27]),
- HashableSectionModel(model: "section 4", items: [10, 12])
- ]
- */
-
- // case 2
- /*
- from = [
- HashableSectionModel(model: "section 10", items: [26]),
- HashableSectionModel(model: "section 7", items: [5, 29]),
- HashableSectionModel(model: "section 1", items: [14]),
- HashableSectionModel(model: "section 5", items: [16]),
- HashableSectionModel(model: "section 4", items: []),
- HashableSectionModel(model: "section 8", items: [3, 15, 19, 23]),
- HashableSectionModel(model: "section 3", items: [20])
- ]
- to = [
- HashableSectionModel(model: "section 10", items: [26]),
- HashableSectionModel(model: "section 1", items: [14]),
- HashableSectionModel(model: "section 9", items: [3]),
- HashableSectionModel(model: "section 5", items: [16, 8]),
- HashableSectionModel(model: "section 8", items: [15, 19, 23]),
- HashableSectionModel(model: "section 3", items: [20]),
- HashableSectionModel(model: "Section 2", items: [7])
- ]
- */
-
- // case 3
- /*
- from = [
- HashableSectionModel(model: "section 4", items: [5]),
- HashableSectionModel(model: "section 6", items: [20, 14]),
- HashableSectionModel(model: "section 9", items: []),
- HashableSectionModel(model: "section 2", items: [2, 26]),
- HashableSectionModel(model: "section 8", items: [23]),
- HashableSectionModel(model: "section 10", items: [8, 18, 13]),
- HashableSectionModel(model: "section 1", items: [28, 25, 6, 11, 10, 29, 24, 7, 19])
- ]
- to = [
- HashableSectionModel(model: "section 4", items: [5]),
- HashableSectionModel(model: "section 6", items: [20, 14]),
- HashableSectionModel(model: "section 9", items: [16]),
- HashableSectionModel(model: "section 7", items: [17, 15, 4]),
- HashableSectionModel(model: "section 2", items: [2, 26, 23]),
- HashableSectionModel(model: "section 8", items: []),
- HashableSectionModel(model: "section 10", items: [8, 18, 13]),
- HashableSectionModel(model: "section 1", items: [28, 25, 6, 11, 10, 29, 24, 7, 19])
- ]
- */
-
- // Generates differential changes suitable for sectioned view consumption.
- // It will not only detect changes between two states, but it will also try to compress those changes into
- // almost minimal set of changes.
- //
- // I know, I know, it's ugly :( Totally agree, but this is the only general way I could find that works 100%, and
- // avoids UITableView quirks.
- //
- // Please take into consideration that I was also convinced about 20 times that I've found a simple general
- // solution, but then UITableView falls apart under stress testing :(
- //
- // Sincerely, if somebody else would present me this 250 lines of code, I would call him a mad man. I would think
- // that there has to be a simpler solution. Well, after 3 days, I'm not convinced any more :)
- //
- // Maybe it can be made somewhat simpler, but don't think it can be made much simpler.
- //
- // The algorithm could take anywhere from 1 to 3 table view transactions to finish the updates.
- //
- // * stage 1 - remove deleted sections and items
- // * stage 2 - move sections into place
- // * stage 3 - fix moved and new items
- //
- // There maybe exists a better division, but time will tell.
- //
- public static func differencesForSectionedView(
- initialSections: [S],
- finalSections: [S])
- throws -> [Changeset] {
- typealias I = S.Item
-
- var result: [Changeset] = []
-
- var sectionCommands = try CommandGenerator.generatorForInitialSections(initialSections, finalSections: finalSections)
-
- result.append(contentsOf: try sectionCommands.generateDeleteSectionsDeletedItemsAndUpdatedItems())
- result.append(contentsOf: try sectionCommands.generateInsertAndMoveSections())
- result.append(contentsOf: try sectionCommands.generateInsertAndMovedItems())
-
- return result
- }
-
-
- @available(*, deprecated, renamed: "differencesForSectionedView(initialSections:finalSections:)")
- public static func differencesForSectionedView(
- _ initialSections: [S],
- finalSections: [S])
- throws -> [Changeset] {
- return try differencesForSectionedView(initialSections: initialSections, finalSections: finalSections)
- }
-
- private struct CommandGenerator {
- typealias Item = S.Item
-
- let initialSections: [S]
- let finalSections: [S]
-
- let initialSectionData: ContiguousArray
- let finalSectionData: ContiguousArray
-
- let initialItemData: ContiguousArray>
- let finalItemData: ContiguousArray>
-
- let initialItemCache: ContiguousArray>
- let finalItemCache: ContiguousArray>
-
- static func generatorForInitialSections(
- _ initialSections: [S],
- finalSections: [S]
- ) throws -> CommandGenerator {
-
- let (initialSectionData, finalSectionData) = try calculateSectionMovements(initialSections: initialSections, finalSections: finalSections)
-
- let initialItemCache = ContiguousArray(initialSections.map {
- ContiguousArray($0.items)
- })
-
- let finalItemCache = ContiguousArray(finalSections.map {
- ContiguousArray($0.items)
- })
-
- let (initialItemData, finalItemData) = try calculateItemMovements(
- initialItemCache: initialItemCache,
- finalItemCache: finalItemCache,
- initialSectionData: initialSectionData,
- finalSectionData: finalSectionData
- )
-
- return CommandGenerator(
- initialSections: initialSections,
- finalSections: finalSections,
-
- initialSectionData: initialSectionData,
- finalSectionData: finalSectionData,
-
- initialItemData: initialItemData,
- finalItemData: finalItemData,
-
- initialItemCache: initialItemCache,
- finalItemCache: finalItemCache
- )
- }
-
- static func calculateItemMovements(
- initialItemCache: ContiguousArray>,
- finalItemCache: ContiguousArray>,
- initialSectionData: ContiguousArray,
- finalSectionData: ContiguousArray) throws
- -> (ContiguousArray>, ContiguousArray>) {
-
- var (initialItemData, finalItemData) = try Diff.calculateAssociatedData(
- initialItemCache: initialItemCache,
- finalItemCache: finalItemCache
- )
-
- let findNextUntouchedOldIndex = { (initialSectionIndex: Int, initialSearchIndex: Int?) -> Int? in
- guard var i2 = initialSearchIndex else {
- return nil
- }
-
- while i2 < initialSectionData[initialSectionIndex].itemCount {
- if initialItemData[initialSectionIndex][i2].event == .untouched {
- return i2
- }
-
- i2 = i2 + 1
- }
-
- return nil
- }
-
- // first mark deleted items
- for i in 0 ..< initialItemCache.count {
- guard let _ = initialSectionData[i].moveIndex else {
- continue
- }
-
- var indexAfterDelete = 0
- for j in 0 ..< initialItemCache[i].count {
-
- guard let finalIndexPath = initialItemData[i][j].moveIndex else {
- initialItemData[i][j].event = .deleted
- continue
- }
-
- // from this point below, section has to be move type because it's initial and not deleted
-
- // because there is no move to inserted section
- if finalSectionData[finalIndexPath.sectionIndex].event == .inserted {
- initialItemData[i][j].event = .deleted
- continue
- }
-
- initialItemData[i][j].indexAfterDelete = indexAfterDelete
- indexAfterDelete += 1
- }
- }
-
- // mark moved or moved automatically
- for i in 0 ..< finalItemCache.count {
- guard let originalSectionIndex = finalSectionData[i].moveIndex else {
- continue
- }
-
- var untouchedIndex: Int? = 0
- for j in 0 ..< finalItemCache[i].count {
- untouchedIndex = findNextUntouchedOldIndex(originalSectionIndex, untouchedIndex)
-
- guard let originalIndex = finalItemData[i][j].moveIndex else {
- finalItemData[i][j].event = .inserted
- continue
- }
-
- // In case trying to move from deleted section, abort, otherwise it will crash table view
- if initialSectionData[originalIndex.sectionIndex].event == .deleted {
- finalItemData[i][j].event = .inserted
- continue
- }
- // original section can't be inserted
- else if initialSectionData[originalIndex.sectionIndex].event == .inserted {
- try precondition(false, "New section in initial sections, that is wrong")
- }
-
- let initialSectionEvent = initialSectionData[originalIndex.sectionIndex].event
- try precondition(initialSectionEvent == .moved || initialSectionEvent == .movedAutomatically, "Section not moved")
-
- let eventType = originalIndex == ItemPath(sectionIndex: originalSectionIndex, itemIndex: untouchedIndex ?? -1)
- ? EditEvent.movedAutomatically : EditEvent.moved
-
- initialItemData[originalIndex.sectionIndex][originalIndex.itemIndex].event = eventType
- finalItemData[i][j].event = eventType
- }
- }
-
- return (initialItemData, finalItemData)
- }
-
- static func calculateSectionMovements(initialSections: [S], finalSections: [S]) throws
- -> (ContiguousArray, ContiguousArray) {
-
- let initialSectionIndexes = try Diff.indexSections(initialSections)
-
- var initialSectionData = ContiguousArray(repeating: SectionAssociatedData.initial, count: initialSections.count)
- var finalSectionData = ContiguousArray(repeating: SectionAssociatedData.initial, count: finalSections.count)
-
- for (i, section) in finalSections.enumerated() {
- finalSectionData[i].itemCount = finalSections[i].items.count
- guard let initialSectionIndex = initialSectionIndexes[section.identity] else {
- continue
- }
-
- if initialSectionData[initialSectionIndex].moveIndex != nil {
- throw Error.duplicateSection(section: section)
- }
-
- initialSectionData[initialSectionIndex].moveIndex = i
- finalSectionData[i].moveIndex = initialSectionIndex
- }
-
- var sectionIndexAfterDelete = 0
-
- // deleted sections
- for i in 0 ..< initialSectionData.count {
- initialSectionData[i].itemCount = initialSections[i].items.count
- if initialSectionData[i].moveIndex == nil {
- initialSectionData[i].event = .deleted
- continue
- }
-
- initialSectionData[i].indexAfterDelete = sectionIndexAfterDelete
- sectionIndexAfterDelete += 1
- }
-
- // moved sections
-
- var untouchedOldIndex: Int? = 0
- let findNextUntouchedOldIndex = { (initialSearchIndex: Int?) -> Int? in
- guard var i = initialSearchIndex else {
- return nil
- }
-
- while i < initialSections.count {
- if initialSectionData[i].event == .untouched {
- return i
- }
-
- i = i + 1
- }
-
- return nil
- }
-
- // inserted and moved sections {
- // this should fix all sections and move them into correct places
- // 2nd stage
- for i in 0 ..< finalSections.count {
- untouchedOldIndex = findNextUntouchedOldIndex(untouchedOldIndex)
-
- // oh, it did exist
- if let oldSectionIndex = finalSectionData[i].moveIndex {
- let moveType = oldSectionIndex != untouchedOldIndex ? EditEvent.moved : EditEvent.movedAutomatically
-
- finalSectionData[i].event = moveType
- initialSectionData[oldSectionIndex].event = moveType
- }
- else {
- finalSectionData[i].event = .inserted
- }
- }
-
- // inserted sections
- for (i, section) in finalSectionData.enumerated() {
- if section.moveIndex == nil {
- _ = finalSectionData[i].event == .inserted
- }
- }
-
- return (initialSectionData, finalSectionData)
- }
-
- mutating func generateDeleteSectionsDeletedItemsAndUpdatedItems() throws -> [Changeset] {
- var deletedSections = [Int]()
-
- var deletedItems = [ItemPath]()
- var updatedItems = [ItemPath]()
-
- var afterDeleteState = [S]()
-
- // mark deleted items {
- // 1rst stage again (I know, I know ...)
- for (i, initialItems) in initialItemCache.enumerated() {
- let event = initialSectionData[i].event
-
- // Deleted section will take care of deleting child items.
- // In case of moving an item from deleted section, tableview will
- // crash anyway, so this is not limiting anything.
- if event == .deleted {
- deletedSections.append(i)
- continue
- }
-
- var afterDeleteItems: [S.Item] = []
- for j in 0 ..< initialItems.count {
- let event = initialItemData[i][j].event
- switch event {
- case .deleted:
- deletedItems.append(ItemPath(sectionIndex: i, itemIndex: j))
- case .moved, .movedAutomatically:
- let finalItemIndex = try initialItemData[i][j].moveIndex.unwrap()
- let finalItem = finalItemCache[finalItemIndex.sectionIndex][finalItemIndex.itemIndex]
- if finalItem != initialSections[i].items[j] {
- updatedItems.append(ItemPath(sectionIndex: i, itemIndex: j))
- }
- afterDeleteItems.append(finalItem)
- default:
- try precondition(false, "Unhandled case")
- }
- }
-
- afterDeleteState.append(try S.init(safeOriginal: initialSections[i], safeItems: afterDeleteItems))
- }
- // }
-
- if deletedItems.isEmpty && deletedSections.isEmpty && updatedItems.isEmpty {
- return []
- }
-
- return [Changeset(
- finalSections: afterDeleteState,
- deletedSections: deletedSections,
- deletedItems: deletedItems,
- updatedItems: updatedItems
- )]
- }
-
- func generateInsertAndMoveSections() throws -> [Changeset] {
-
- var movedSections = [(from: Int, to: Int)]()
- var insertedSections = [Int]()
-
- for i in 0 ..< initialSections.count {
- switch initialSectionData[i].event {
- case .deleted:
- break
- case .moved:
- movedSections.append((from: try initialSectionData[i].indexAfterDelete.unwrap(), to: try initialSectionData[i].moveIndex.unwrap()))
- case .movedAutomatically:
- break
- default:
- try precondition(false, "Unhandled case in initial sections")
- }
- }
-
- for i in 0 ..< finalSections.count {
- switch finalSectionData[i].event {
- case .inserted:
- insertedSections.append(i)
- default:
- break
- }
- }
-
- if insertedSections.isEmpty && movedSections.isEmpty {
- return []
- }
-
- // sections should be in place, but items should be original without deleted ones
- let sectionsAfterChange: [S] = try self.finalSections.enumerated().map { i, s -> S in
- let event = self.finalSectionData[i].event
-
- if event == .inserted {
- // it's already set up
- return s
- }
- else if event == .moved || event == .movedAutomatically {
- let originalSectionIndex = try finalSectionData[i].moveIndex.unwrap()
- let originalSection = initialSections[originalSectionIndex]
-
- var items: [S.Item] = []
- items.reserveCapacity(originalSection.items.count)
- let itemAssociatedData = self.initialItemData[originalSectionIndex]
- for j in 0 ..< originalSection.items.count {
- let initialData = itemAssociatedData[j]
-
- guard initialData.event != .deleted else {
- continue
- }
-
- guard let finalIndex = initialData.moveIndex else {
- try precondition(false, "Item was moved, but no final location.")
- continue
- }
-
- items.append(finalItemCache[finalIndex.sectionIndex][finalIndex.itemIndex])
- }
-
- let modifiedSection = try S.init(safeOriginal: s, safeItems: items)
-
- return modifiedSection
- }
- else {
- try precondition(false, "This is weird, this shouldn't happen")
- return s
- }
- }
-
- return [Changeset(
- finalSections: sectionsAfterChange,
- insertedSections: insertedSections,
- movedSections: movedSections
- )]
- }
-
- mutating func generateInsertAndMovedItems() throws -> [Changeset] {
- var insertedItems = [ItemPath]()
- var movedItems = [(from: ItemPath, to: ItemPath)]()
-
- // mark new and moved items {
- // 3rd stage
- for i in 0 ..< finalSections.count {
- let finalSection = finalSections[i]
-
- let sectionEvent = finalSectionData[i].event
- // new and deleted sections cause reload automatically
- if sectionEvent != .moved && sectionEvent != .movedAutomatically {
- continue
- }
-
- for j in 0 ..< finalSection.items.count {
- let currentItemEvent = finalItemData[i][j].event
-
- try precondition(currentItemEvent != .untouched, "Current event is not untouched")
-
- let event = finalItemData[i][j].event
-
- switch event {
- case .inserted:
- insertedItems.append(ItemPath(sectionIndex: i, itemIndex: j))
- case .moved:
- let originalIndex = try finalItemData[i][j].moveIndex.unwrap()
- let finalSectionIndex = try initialSectionData[originalIndex.sectionIndex].moveIndex.unwrap()
- let moveFromItemWithIndex = try initialItemData[originalIndex.sectionIndex][originalIndex.itemIndex].indexAfterDelete.unwrap()
-
- let moveCommand = (
- from: ItemPath(sectionIndex: finalSectionIndex, itemIndex: moveFromItemWithIndex),
- to: ItemPath(sectionIndex: i, itemIndex: j)
- )
- movedItems.append(moveCommand)
- default:
- break
- }
- }
- }
- // }
-
- if insertedItems.isEmpty && movedItems.isEmpty {
- return []
- }
- return [Changeset(
- finalSections: finalSections,
- insertedItems: insertedItems,
- movedItems: movedItems
- )]
- }
- }
-}
diff --git a/Pods/Differentiator/Sources/Differentiator/IdentifiableType.swift b/Pods/Differentiator/Sources/Differentiator/IdentifiableType.swift
deleted file mode 100644
index 9bda068..0000000
--- a/Pods/Differentiator/Sources/Differentiator/IdentifiableType.swift
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-// IdentifiableType.swift
-// RxDataSources
-//
-// Created by Krunoslav Zaher on 1/6/16.
-// Copyright © 2016 Krunoslav Zaher. All rights reserved.
-//
-
-import Foundation
-
-public protocol IdentifiableType {
- associatedtype Identity: Hashable
-
- var identity : Identity { get }
-}
\ No newline at end of file
diff --git a/Pods/Differentiator/Sources/Differentiator/IdentifiableValue.swift b/Pods/Differentiator/Sources/Differentiator/IdentifiableValue.swift
deleted file mode 100644
index 6d02d65..0000000
--- a/Pods/Differentiator/Sources/Differentiator/IdentifiableValue.swift
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// IdentifiableValue.swift
-// RxDataSources
-//
-// Created by Krunoslav Zaher on 1/7/16.
-// Copyright © 2016 Krunoslav Zaher. All rights reserved.
-//
-
-import Foundation
-
-public struct IdentifiableValue {
- public let value: Value
-}
-
-extension IdentifiableValue
- : IdentifiableType {
-
- public typealias Identity = Value
-
- public var identity : Identity {
- return value
- }
-}
-
-extension IdentifiableValue
- : Equatable
- , CustomStringConvertible
- , CustomDebugStringConvertible {
-
- public var description: String {
- return "\(value)"
- }
-
- public var debugDescription: String {
- return "\(value)"
- }
-}
-
-public func == (lhs: IdentifiableValue, rhs: IdentifiableValue) -> Bool {
- return lhs.value == rhs.value
-}
diff --git a/Pods/Differentiator/Sources/Differentiator/ItemPath.swift b/Pods/Differentiator/Sources/Differentiator/ItemPath.swift
deleted file mode 100644
index 9551e11..0000000
--- a/Pods/Differentiator/Sources/Differentiator/ItemPath.swift
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// ItemPath.swift
-// RxDataSources
-//
-// Created by Krunoslav Zaher on 1/9/16.
-// Copyright © 2016 Krunoslav Zaher. All rights reserved.
-//
-
-import Foundation
-
-public struct ItemPath {
- public let sectionIndex: Int
- public let itemIndex: Int
-
- public init(sectionIndex: Int, itemIndex: Int) {
- self.sectionIndex = sectionIndex
- self.itemIndex = itemIndex
- }
-}
-
-extension ItemPath : Equatable {
-
-}
-
-public func == (lhs: ItemPath, rhs: ItemPath) -> Bool {
- return lhs.sectionIndex == rhs.sectionIndex && lhs.itemIndex == rhs.itemIndex
-}
-
-extension ItemPath: Hashable {
-
- public var hashValue: Int {
- return sectionIndex.byteSwapped.hashValue ^ itemIndex.hashValue
- }
-
-}
diff --git a/Pods/Differentiator/Sources/Differentiator/Optional+Extensions.swift b/Pods/Differentiator/Sources/Differentiator/Optional+Extensions.swift
deleted file mode 100644
index 2a642ff..0000000
--- a/Pods/Differentiator/Sources/Differentiator/Optional+Extensions.swift
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// Optional+Extensions.swift
-// RxDataSources
-//
-// Created by Krunoslav Zaher on 1/8/16.
-// Copyright © 2016 Krunoslav Zaher. All rights reserved.
-//
-
-import Foundation
-
-extension Optional {
- func unwrap() throws -> Wrapped {
- if let unwrapped = self {
- return unwrapped
- }
- else {
- debugFatalError("Error during unwrapping optional")
- throw DifferentiatorError.unwrappingOptional
- }
- }
-}
diff --git a/Pods/Differentiator/Sources/Differentiator/SectionModel.swift b/Pods/Differentiator/Sources/Differentiator/SectionModel.swift
deleted file mode 100644
index 1367c2a..0000000
--- a/Pods/Differentiator/Sources/Differentiator/SectionModel.swift
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// SectionModel.swift
-// RxDataSources
-//
-// Created by Krunoslav Zaher on 6/16/15.
-// Copyright © 2015 Krunoslav Zaher. All rights reserved.
-//
-
-import Foundation
-
-public struct SectionModel {
- public var model: Section
- public var items: [Item]
-
- public init(model: Section, items: [Item]) {
- self.model = model
- self.items = items
- }
-}
-
-extension SectionModel
- : SectionModelType {
- public typealias Identity = Section
- public typealias Item = ItemType
-
- public var identity: Section {
- return model
- }
-}
-
-extension SectionModel
- : CustomStringConvertible {
-
- public var description: String {
- return "\(self.model) > \(items)"
- }
-}
-
-extension SectionModel {
- public init(original: SectionModel, items: [Item]) {
- self.model = original.model
- self.items = items
- }
-}
diff --git a/Pods/Differentiator/Sources/Differentiator/SectionModelType.swift b/Pods/Differentiator/Sources/Differentiator/SectionModelType.swift
deleted file mode 100644
index 1bbfb2d..0000000
--- a/Pods/Differentiator/Sources/Differentiator/SectionModelType.swift
+++ /dev/null
@@ -1,17 +0,0 @@
-//
-// SectionModelType.swift
-// RxDataSources
-//
-// Created by Krunoslav Zaher on 6/28/15.
-// Copyright © 2015 Krunoslav Zaher. All rights reserved.
-//
-
-import Foundation
-
-public protocol SectionModelType {
- associatedtype Item
-
- var items: [Item] { get }
-
- init(original: Self, items: [Item])
-}
\ No newline at end of file
diff --git a/Pods/Differentiator/Sources/Differentiator/Utilities.swift b/Pods/Differentiator/Sources/Differentiator/Utilities.swift
deleted file mode 100644
index c884f57..0000000
--- a/Pods/Differentiator/Sources/Differentiator/Utilities.swift
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Utilities.swift
-// RxDataSources
-//
-// Created by muukii on 8/2/17.
-// Copyright © 2017 kzaher. All rights reserved.
-//
-
-import Foundation
-
-enum DifferentiatorError : Error {
- case unwrappingOptional
- case preconditionFailed(message: String)
-}
-
-func precondition(_ condition: Bool, _ message: @autoclosure() -> String) throws -> () {
- if condition {
- return
- }
- debugFatalError("Precondition failed")
-
- throw DifferentiatorError.preconditionFailed(message: message())
-}
-
-func debugFatalError(_ error: Error) {
- debugFatalError("\(error)")
-}
-
-func debugFatalError(_ message: String) {
- #if DEBUG
- fatalError(message)
- #else
- print(message)
- #endif
-}
diff --git a/Pods/Kingfisher/LICENSE b/Pods/Kingfisher/LICENSE
deleted file mode 100644
index 5023261..0000000
--- a/Pods/Kingfisher/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2018 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
-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.
-
diff --git a/Pods/Kingfisher/README.md b/Pods/Kingfisher/README.md
deleted file mode 100644
index fa38fc1..0000000
--- a/Pods/Kingfisher/README.md
+++ /dev/null
@@ -1,116 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-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.
-
-## 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] Built-in transition animation when setting images.
-- [x] Customizable placeholder while loading images.
-- [x] Extensible image processing and image format support.
-
-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")
-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.
-
-For more examples of using Kingfisher, take a look at the [Cheat Sheet](https://github.com/onevcat/Kingfisher/wiki/Cheat-Sheet).
-
-## Requirements
-
-- iOS 8.0+ / macOS 10.10+ / tvOS 9.0+ / watchOS 2.0+
-- Swift 4 (Kingfisher 4.x), Swift 3 (Kingfisher 3.x)
-
-Main development of Kingfisher is based on Swift 4. Only critical bug fixes will be applied to Kingfisher 3.x.
-
-- 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.
-
-## Next Steps
-
-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](http://onevcat.github.io/Kingfisher/) - Lastly, please remember to read the full whenever you may need a more detailed reference.
-
-## Other
-
-### Future of Kingfisher
-
-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.
-
-### Developments and Tests
-
-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. :)
-
-### 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?
-
-### Contact
-
-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.
-
-## Contributors
-
-This project exists thanks to all the people who contribute. [[Contribute]](https://github.com/onevcat/Kingfisher/blob/master/CONTRIBUTING.md).
-
-
-
-## Backers
-
-Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/kingfisher#backer)]
-
-
-
-
-## Sponsors
-
-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)]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-### License
-
-Kingfisher is released under the MIT license. See LICENSE for details.
-
-
diff --git a/Pods/Kingfisher/Sources/AnimatedImageView.swift b/Pods/Kingfisher/Sources/AnimatedImageView.swift
deleted file mode 100755
index 340adc3..0000000
--- a/Pods/Kingfisher/Sources/AnimatedImageView.swift
+++ /dev/null
@@ -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.. 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 and 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(_ value: T) -> [T] {
- return [value]
-}
diff --git a/Pods/Kingfisher/Sources/Box.swift b/Pods/Kingfisher/Sources/Box.swift
deleted file mode 100644
index 7714a68..0000000
--- a/Pods/Kingfisher/Sources/Box.swift
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Box.swift
-// Kingfisher
-//
-// Created by Wei Wang on 2018/3/17.
-// Copyright (c) 2018 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
-// 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 {
- let value: T
-
- init(_ value: T) {
- self.value = value
- }
-}
diff --git a/Pods/Kingfisher/Sources/CacheSerializer.swift b/Pods/Kingfisher/Sources/CacheSerializer.swift
deleted file mode 100644
index c3b6a27..0000000
--- a/Pods/Kingfisher/Sources/CacheSerializer.swift
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// CacheSerializer.swift
-// Kingfisher
-//
-// Created by Wei Wang on 2016/09/02.
-//
-// Copyright (c) 2018 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
-// 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(
- data: data,
- scale: options.scaleFactor,
- preloadAllAnimationData: options.preloadAllAnimationData,
- onlyFirstFrame: options.onlyLoadFirstFrame)
- }
-}
diff --git a/Pods/Kingfisher/Sources/Filter.swift b/Pods/Kingfisher/Sources/Filter.swift
deleted file mode 100644
index 0df99e4..0000000
--- a/Pods/Kingfisher/Sources/Filter.swift
+++ /dev/null
@@ -1,144 +0,0 @@
-//
-// Filter.swift
-// Kingfisher
-//
-// Created by Wei Wang on 2016/08/31.
-//
-// Copyright (c) 2018 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
-// 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
- }
-
-}
diff --git a/Pods/Kingfisher/Sources/FormatIndicatedCacheSerializer.swift b/Pods/Kingfisher/Sources/FormatIndicatedCacheSerializer.swift
deleted file mode 100644
index 71f5856..0000000
--- a/Pods/Kingfisher/Sources/FormatIndicatedCacheSerializer.swift
+++ /dev/null
@@ -1,96 +0,0 @@
-//
-// RequestModifier.swift
-// Kingfisher
-//
-// Created by Junyu Kuang on 5/28/17.
-//
-// Copyright (c) 2018 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
-// 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(
- data: data,
- scale: options.scaleFactor,
- preloadAllAnimationData: options.preloadAllAnimationData,
- onlyFirstFrame: options.onlyLoadFirstFrame)
- }
-}
diff --git a/Pods/Kingfisher/Sources/Image.swift b/Pods/Kingfisher/Sources/Image.swift
deleted file mode 100755
index 66ae7a6..0000000
--- a/Pods/Kingfisher/Sources/Image.swift
+++ /dev/null
@@ -1,1045 +0,0 @@
-//
-// Image.swift
-// Kingfisher
-//
-// Created by Wei Wang on 16/1/6.
-//
-// Copyright (c) 2018 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
-// 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(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.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.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.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(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 {
- 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
-
diff --git a/Pods/Kingfisher/Sources/ImageCache.swift b/Pods/Kingfisher/Sources/ImageCache.swift
deleted file mode 100755
index 74b5dec..0000000
--- a/Pods/Kingfisher/Sources/ImageCache.swift
+++ /dev/null
@@ -1,742 +0,0 @@
-//
-// ImageCache.swift
-// Kingfisher
-//
-// Created by Wei Wang on 15/4/6.
-//
-// Copyright (c) 2018 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
-// 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()
-
- /// 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 = [.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.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 `` 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)")
- }
- }
-}
diff --git a/Pods/Kingfisher/Sources/ImageDownloader.swift b/Pods/Kingfisher/Sources/ImageDownloader.swift
deleted file mode 100755
index 4a24735..0000000
--- a/Pods/Kingfisher/Sources/ImageDownloader.swift
+++ /dev/null
@@ -1,677 +0,0 @@
-//
-// ImageDownloader.swift
-// Kingfisher
-//
-// Created by Wei Wang on 15/4/6.
-//
-// Copyright (c) 2018 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
-// 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?
-
- /// 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 {}
-
diff --git a/Pods/Kingfisher/Sources/ImageModifier.swift b/Pods/Kingfisher/Sources/ImageModifier.swift
deleted file mode 100644
index ddd7ffc..0000000
--- a/Pods/Kingfisher/Sources/ImageModifier.swift
+++ /dev/null
@@ -1,191 +0,0 @@
-//
-// ImageModifier.swift
-// Kingfisher
-//
-// Created by Ethan Gill on 2017/11/28.
-//
-// Copyright (c) 2018 Ethan Gill
-//
-// 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
diff --git a/Pods/Kingfisher/Sources/ImagePrefetcher.swift b/Pods/Kingfisher/Sources/ImagePrefetcher.swift
deleted file mode 100755
index 7a2a24b..0000000
--- a/Pods/Kingfisher/Sources/ImagePrefetcher.swift
+++ /dev/null
@@ -1,277 +0,0 @@
-//
-// ImagePrefetcher.swift
-// Kingfisher
-//
-// Created by Claire Knight on 24/02/2016
-//
-// Copyright (c) 2018 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
-// 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
- 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
- }
- }
-}
diff --git a/Pods/Kingfisher/Sources/ImageProcessor.swift b/Pods/Kingfisher/Sources/ImageProcessor.swift
deleted file mode 100644
index 9d63cda..0000000
--- a/Pods/Kingfisher/Sources/ImageProcessor.swift
+++ /dev/null
@@ -1,713 +0,0 @@
-//
-// ImageProcessor.swift
-// Kingfisher
-//
-// Created by Wei Wang on 2016/08/26.
-//
-// Copyright (c) 2018 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
-// 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(
- 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)
- }
-}
diff --git a/Pods/Kingfisher/Sources/ImageTransition.swift b/Pods/Kingfisher/Sources/ImageTransition.swift
deleted file mode 100755
index 3bc13b8..0000000
--- a/Pods/Kingfisher/Sources/ImageTransition.swift
+++ /dev/null
@@ -1,128 +0,0 @@
-//
-// ImageTransition.swift
-// Kingfisher
-//
-// Created by Wei Wang on 15/9/18.
-//
-// Copyright (c) 2018 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
-// 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
diff --git a/Pods/Kingfisher/Sources/ImageView+Kingfisher.swift b/Pods/Kingfisher/Sources/ImageView+Kingfisher.swift
deleted file mode 100755
index cb230fb..0000000
--- a/Pods/Kingfisher/Sources/ImageView+Kingfisher.swift
+++ /dev/null
@@ -1,263 +0,0 @@
-//
-// ImageView+Kingfisher.swift
-// Kingfisher
-//
-// Created by Wei Wang on 15/4/6.
-//
-// Copyright (c) 2018 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
-// 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 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 }
-}
diff --git a/Pods/Kingfisher/Sources/Indicator.swift b/Pods/Kingfisher/Sources/Indicator.swift
deleted file mode 100644
index f8fcf09..0000000
--- a/Pods/Kingfisher/Sources/Indicator.swift
+++ /dev/null
@@ -1,203 +0,0 @@
-//
-// Indicator.swift
-// Kingfisher
-//
-// Created by João D. Moreira on 30/08/16.
-//
-// Copyright (c) 2018 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
-// 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
- }
-}
diff --git a/Pods/Kingfisher/Sources/Kingfisher.h b/Pods/Kingfisher/Sources/Kingfisher.h
deleted file mode 100644
index 0e11d43..0000000
--- a/Pods/Kingfisher/Sources/Kingfisher.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Kingfisher.h
-// Kingfisher
-//
-// Created by Wei Wang on 15/4/6.
-//
-// Copyright (c) 2018 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
-// 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
-
-//! 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
-
-
diff --git a/Pods/Kingfisher/Sources/Kingfisher.swift b/Pods/Kingfisher/Sources/Kingfisher.swift
deleted file mode 100644
index 7958060..0000000
--- a/Pods/Kingfisher/Sources/Kingfisher.swift
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// Kingfisher.swift
-// Kingfisher
-//
-// Created by Wei Wang on 16/9/14.
-//
-// Copyright (c) 2018 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
-// 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 {
- 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 {
- return Kingfisher(self)
- }
-}
-
-extension Image: KingfisherCompatible { }
-#if !os(watchOS)
-extension ImageView: KingfisherCompatible { }
-extension Button: KingfisherCompatible { }
-#else
-extension WKInterfaceImage: KingfisherCompatible { }
-#endif
diff --git a/Pods/Kingfisher/Sources/KingfisherManager.swift b/Pods/Kingfisher/Sources/KingfisherManager.swift
deleted file mode 100755
index cb2a14e..0000000
--- a/Pods/Kingfisher/Sources/KingfisherManager.swift
+++ /dev/null
@@ -1,297 +0,0 @@
-//
-// KingfisherManager.swift
-// Kingfisher
-//
-// Created by Wei Wang on 15/4/6.
-//
-// Copyright (c) 2018 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
-// 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)
- }
- }
- }
- }
- }
- }
-}
diff --git a/Pods/Kingfisher/Sources/KingfisherOptionsInfo.swift b/Pods/Kingfisher/Sources/KingfisherOptionsInfo.swift
deleted file mode 100755
index 68833a1..0000000
--- a/Pods/Kingfisher/Sources/KingfisherOptionsInfo.swift
+++ /dev/null
@@ -1,364 +0,0 @@
-//
-// KingfisherOptionsInfo.swift
-// Kingfisher
-//
-// Created by Wei Wang on 15/4/23.
-//
-// Copyright (c) 2018 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
-// 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 }
- }
-}
diff --git a/Pods/Kingfisher/Sources/Placeholder.swift b/Pods/Kingfisher/Sources/Placeholder.swift
deleted file mode 100755
index 3ebaf0b..0000000
--- a/Pods/Kingfisher/Sources/Placeholder.swift
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// Placeholder.swift
-// Kingfisher
-//
-// Created by Tieme van Veen on 28/08/2017.
-//
-// Copyright (c) 2018 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
-// 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()
- }
-}
diff --git a/Pods/Kingfisher/Sources/RequestModifier.swift b/Pods/Kingfisher/Sources/RequestModifier.swift
deleted file mode 100644
index 1e099bf..0000000
--- a/Pods/Kingfisher/Sources/RequestModifier.swift
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// RequestModifier.swift
-// Kingfisher
-//
-// Created by Wei Wang on 2016/09/05.
-//
-// Copyright (c) 2018 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
-// 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
- }
-}
diff --git a/Pods/Kingfisher/Sources/Resource.swift b/Pods/Kingfisher/Sources/Resource.swift
deleted file mode 100755
index c71f24d..0000000
--- a/Pods/Kingfisher/Sources/Resource.swift
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// Resource.swift
-// Kingfisher
-//
-// Created by Wei Wang on 15/4/6.
-//
-// Copyright (c) 2018 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
-// 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 }
-}
diff --git a/Pods/Kingfisher/Sources/String+MD5.swift b/Pods/Kingfisher/Sources/String+MD5.swift
deleted file mode 100755
index fa173a9..0000000
--- a/Pods/Kingfisher/Sources/String+MD5.swift
+++ /dev/null
@@ -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
-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(_ value: T, length: Int? = nil) -> [UInt8] {
- let totalBytes = length ?? (MemoryLayout.size * 8)
-
- let valuePointer = UnsafeMutablePointer.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...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.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 { get }
-
- /** Common part for hash calculation. Prepare header data. */
- func prepare(_ len: Int) -> Array
-}
-
-extension HashProtocol {
-
- func prepare(_ len: Int) -> Array {
- 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(repeating: 0, count: counter)
- return tmpMessage
- }
-}
-
-func toUInt32Array(_ slice: ArraySlice) -> Array {
- var result = Array()
- result.reserveCapacity(16)
-
- for idx in stride(from: slice.startIndex, to: slice.endIndex, by: MemoryLayout.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? {
- let end = min(chunkSize, data.count - offset)
- let result = data[offset.. 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
- }
-}
diff --git a/Pods/Kingfisher/Sources/ThreadHelper.swift b/Pods/Kingfisher/Sources/ThreadHelper.swift
deleted file mode 100755
index a737b6e..0000000
--- a/Pods/Kingfisher/Sources/ThreadHelper.swift
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// ThreadHelper.swift
-// Kingfisher
-//
-// Created by Wei Wang on 15/10/9.
-//
-// Copyright (c) 2018 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
-// 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() }
- }
- }
-}
diff --git a/Pods/Kingfisher/Sources/UIButton+Kingfisher.swift b/Pods/Kingfisher/Sources/UIButton+Kingfisher.swift
deleted file mode 100755
index 344c489..0000000
--- a/Pods/Kingfisher/Sources/UIButton+Kingfisher.swift
+++ /dev/null
@@ -1,274 +0,0 @@
-//
-// UIButton+Kingfisher.swift
-// Kingfisher
-//
-// Created by Wei Wang on 15/4/13.
-//
-// Copyright (c) 2018 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
-// 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)
- }
-}
diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock
deleted file mode 100644
index ad74802..0000000
--- a/Pods/Manifest.lock
+++ /dev/null
@@ -1,87 +0,0 @@
-PODS:
- - Differentiator (3.1.0)
- - Kingfisher (4.10.1)
- - Nimble (8.0.2)
- - Quick (1.3.4)
- - RxAppState (1.5.0):
- - RxCocoa (~> 4.4)
- - RxSwift (~> 4.4)
- - RxAtomic (4.4.2)
- - RxBlocking (4.5.0):
- - RxSwift (>= 4.4.2, ~> 4.4)
- - RxCocoa (4.4.2):
- - RxSwift (>= 4.4.2, ~> 4.4)
- - RxDataSources (3.1.0):
- - Differentiator (~> 3.0)
- - RxCocoa (~> 4.0)
- - RxSwift (~> 4.0)
- - RxKeyboard (0.9.0):
- - RxCocoa (>= 4.3.1)
- - RxSwift (>= 4.3.1)
- - RxOptional (3.6.2):
- - RxCocoa (~> 4.0)
- - RxSwift (~> 4.0)
- - RxSwift (4.4.2):
- - RxAtomic (>= 4.4.2, ~> 4.4)
- - RxTest (4.5.0):
- - RxSwift (>= 4.4.2, ~> 4.4)
- - SnapKit (4.2.0)
- - Then (2.4.0)
- - Toaster (2.1.1)
-
-DEPENDENCIES:
- - Kingfisher (~> 4.10.1)
- - Nimble (~> 8.0.0)
- - Quick (~> 1.3.1)
- - RxAppState
- - RxBlocking (~> 4.0)
- - RxCocoa (~> 4.4.0)
- - RxDataSources (~> 3.1.0)
- - RxKeyboard (~> 0.9.0)
- - RxOptional (~> 3.6.2)
- - RxSwift (~> 4.4.0)
- - RxTest (~> 4.0)
- - SnapKit (~> 4.2.0)
- - Then (~> 2.4.0)
- - Toaster (~> 2.1.0)
-
-SPEC REPOS:
- https://github.com/CocoaPods/Specs.git:
- - Differentiator
- - Kingfisher
- - Nimble
- - Quick
- - RxAppState
- - RxAtomic
- - RxBlocking
- - RxCocoa
- - RxDataSources
- - RxKeyboard
- - RxOptional
- - RxSwift
- - RxTest
- - SnapKit
- - Then
- - Toaster
-
-SPEC CHECKSUMS:
- Differentiator: be49ca3408f0ecfc761e4c7763d20c62be01b9ad
- Kingfisher: c148cd7b47ebde9989f6bc7c27dcaa79d81279a0
- Nimble: 622629381bda1dd5678162f21f1368cec7cbba60
- Quick: f4f7f063c524394c73ed93ac70983c609805d481
- RxAppState: 46cae19e582daf7283a8f9ef553e7c049e1565b4
- RxAtomic: d00e97c10db88c6f08540e0bf2752fc5a2404167
- RxBlocking: 79413e4d916f44bb3e113c5b2cc059e36fe58910
- RxCocoa: 477990dc3b4c3ff55fb0ac77e1cc06244e0aaec8
- RxDataSources: a843bad90c29817f5923ec8163f4af2de084ceb3
- RxKeyboard: 4f782303f499f41577b41c96c6a9a5d7acd51a47
- RxOptional: 80426a0ddbd092573e4c482d8cc13302078c4d5e
- RxSwift: 74c29b693c8e42b0f64400e8b06564575742d649
- RxTest: 3ccb66bfbace0bf7df1c43a7c75d046f8ce60372
- SnapKit: fe8a619752f3f27075cc9a90244d75c6c3f27e2a
- Then: 71866660c7af35a7343831f7668e7cd2b62ee0f2
- Toaster: a6c9532de1ded8105e77376f7dffeb2e12b46dbb
-
-PODFILE CHECKSUM: 40af1741cc4f5d8f03824484297ed0554bb9cc30
-
-COCOAPODS: 1.8.3
diff --git a/Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift b/Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift
deleted file mode 100644
index 3e89e23..0000000
--- a/Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// CwlCatchException.swift
-// CwlAssertionTesting
-//
-// Created by Matt Gallagher on 2016/01/10.
-// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-
-import Foundation
-
-#if SWIFT_PACKAGE
-import CwlCatchExceptionSupport
-#endif
-
-private func catchReturnTypeConverter(_ type: T.Type, block: () -> Void) -> T? {
- return catchExceptionOfKind(type, block) as? T
-}
-
-extension NSException {
- public static func catchException(in block: () -> Void) -> Self? {
- return catchReturnTypeConverter(self, block: block)
- }
-}
diff --git a/Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m b/Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m
deleted file mode 100644
index 8cf414f..0000000
--- a/Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// CwlCatchException.m
-// CwlAssertionTesting
-//
-// Created by Matt Gallagher on 2016/01/10.
-// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-
-#import "CwlCatchException.h"
-
-#if !SWIFT_PACKAGE && NON_SWIFT_PACKAGE
-__attribute__((visibility("hidden")))
-#endif
-NSException* catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)(void)) {
- @try {
- inBlock();
- } @catch (NSException *exception) {
- if ([exception isKindOfClass:type]) {
- return exception;
- } else {
- @throw;
- }
- }
- return nil;
-}
diff --git a/Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h b/Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h
deleted file mode 100644
index 0c8dd87..0000000
--- a/Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// CwlCatchException.h
-// CwlCatchException
-//
-// Created by Matt Gallagher on 2016/01/10.
-// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-
-#import
-
-//! Project version number for CwlCatchException.
-FOUNDATION_EXPORT double CwlCatchExceptionVersionNumber;
-
-//! Project version string for CwlCatchException.
-FOUNDATION_EXPORT const unsigned char CwlCatchExceptionVersionString[];
-
-#if !SWIFT_PACKAGE && NON_SWIFT_PACKAGE
-__attribute__((visibility("hidden")))
-#endif
-NSException* __nullable catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)(void));
diff --git a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m b/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m
deleted file mode 100644
index 8183196..0000000
--- a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// CwlMachBadExceptionHandler.m
-// CwlPreconditionTesting
-//
-// Created by Matt Gallagher on 2016/01/10.
-// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-
-#if defined(__x86_64__)
-
- #import "mach_excServer.h"
- #import "CwlMachBadInstructionHandler.h"
-
- @protocol BadInstructionReply
- +(NSNumber *)receiveReply:(NSValue *)value;
- @end
-
- /// A basic function that receives callbacks from mach_exc_server and relays them to the Swift implemented BadInstructionException.catch_mach_exception_raise_state.
- kern_return_t catch_mach_exception_raise_state(mach_port_t exception_port, exception_type_t exception, const mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, const thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) {
- bad_instruction_exception_reply_t reply = { exception_port, exception, code, codeCnt, flavor, old_state, old_stateCnt, new_state, new_stateCnt };
- Class badInstructionClass = NSClassFromString(@"BadInstructionException");
- NSValue *value = [NSValue valueWithBytes: &reply objCType: @encode(bad_instruction_exception_reply_t)];
- return [[badInstructionClass performSelector: @selector(receiveReply:) withObject: value] intValue];
- }
-
- // The mach port should be configured so that this function is never used.
- kern_return_t catch_mach_exception_raise(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt) {
- assert(false);
- return KERN_FAILURE;
- }
-
- // The mach port should be configured so that this function is never used.
- kern_return_t catch_mach_exception_raise_state_identity(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) {
- assert(false);
- return KERN_FAILURE;
- }
-
-#endif
diff --git a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h b/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h
deleted file mode 100644
index aef59c2..0000000
--- a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h
+++ /dev/null
@@ -1,70 +0,0 @@
-//
-// CwlMachBadInstructionHandler.h
-// CwlPreconditionTesting
-//
-// Created by Matt Gallagher on 2016/01/10.
-// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-
-#import
-#import
-
-NS_ASSUME_NONNULL_BEGIN
-
-extern boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
-
-// The request_mach_exception_raise_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift.
-typedef struct
-{
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_port_descriptor_t thread;
- mach_msg_port_descriptor_t task;
- /* end of the kernel processed data */
- NDR_record_t NDR;
- exception_type_t exception;
- mach_msg_type_number_t codeCnt;
- int64_t code[2];
- int flavor;
- mach_msg_type_number_t old_stateCnt;
- natural_t old_state[224];
-} request_mach_exception_raise_t;
-
-// The reply_mach_exception_raise_state_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift.
-typedef struct
-{
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- int flavor;
- mach_msg_type_number_t new_stateCnt;
- natural_t new_state[224];
-} reply_mach_exception_raise_state_t;
-
-typedef struct
-{
- mach_port_t exception_port;
- exception_type_t exception;
- mach_exception_data_type_t const * _Nullable code;
- mach_msg_type_number_t codeCnt;
- int32_t * _Nullable flavor;
- natural_t const * _Nullable old_state;
- mach_msg_type_number_t old_stateCnt;
- thread_state_t _Nullable new_state;
- mach_msg_type_number_t * _Nullable new_stateCnt;
-} bad_instruction_exception_reply_t;
-
-NS_ASSUME_NONNULL_END
diff --git a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c b/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c
deleted file mode 100644
index 733c564..0000000
--- a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.c
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * IDENTIFICATION:
- * stub generated Sun Jan 29 19:05:29 2017
- * with a MiG generated by bootstrap_cmds-96.20.2
- * OPTIONS:
- */
-
-#if defined(__x86_64__)
-
-/* Module mach_exc */
-
-#define __MIG_check__Request__mach_exc_subsystem__ 1
-
-#include "mach_excServer.h"
-
-#ifndef mig_internal
-#define mig_internal static __inline__
-#endif /* mig_internal */
-
-#ifndef mig_external
-#define mig_external
-#endif /* mig_external */
-
-#if !defined(__MigTypeCheck) && defined(TypeCheck)
-#define __MigTypeCheck TypeCheck /* Legacy setting */
-#endif /* !defined(__MigTypeCheck) */
-
-#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)
-#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */
-#endif /* !defined(__MigKernelSpecificCode) */
-
-#ifndef LimitCheck
-#define LimitCheck 0
-#endif /* LimitCheck */
-
-#ifndef min
-#define min(a,b) ( ((a) < (b))? (a): (b) )
-#endif /* min */
-
-#if !defined(_WALIGN_)
-#define _WALIGN_(x) (((x) + 3) & ~3)
-#endif /* !defined(_WALIGN_) */
-
-#if !defined(_WALIGNSZ_)
-#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))
-#endif /* !defined(_WALIGNSZ_) */
-
-#ifndef UseStaticTemplates
-#define UseStaticTemplates 0
-#endif /* UseStaticTemplates */
-
-#ifndef __DeclareRcvRpc
-#define __DeclareRcvRpc(_NUM_, _NAME_)
-#endif /* __DeclareRcvRpc */
-
-#ifndef __BeforeRcvRpc
-#define __BeforeRcvRpc(_NUM_, _NAME_)
-#endif /* __BeforeRcvRpc */
-
-#ifndef __AfterRcvRpc
-#define __AfterRcvRpc(_NUM_, _NAME_)
-#endif /* __AfterRcvRpc */
-
-#ifndef __DeclareRcvSimple
-#define __DeclareRcvSimple(_NUM_, _NAME_)
-#endif /* __DeclareRcvSimple */
-
-#ifndef __BeforeRcvSimple
-#define __BeforeRcvSimple(_NUM_, _NAME_)
-#endif /* __BeforeRcvSimple */
-
-#ifndef __AfterRcvSimple
-#define __AfterRcvSimple(_NUM_, _NAME_)
-#endif /* __AfterRcvSimple */
-
-#define novalue void
-
-#define msgh_request_port msgh_local_port
-#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits)
-#define msgh_reply_port msgh_remote_port
-#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits)
-
-#define MIG_RETURN_ERROR(X, code) {\
- ((mig_reply_error_t *)X)->RetCode = code;\
- ((mig_reply_error_t *)X)->NDR = NDR_record;\
- return;\
- }
-
-/* Forward Declarations */
-
-
-mig_internal novalue _Xmach_exception_raise
- (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
-
-mig_internal novalue _Xmach_exception_raise_state
- (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
-
-mig_internal novalue _Xmach_exception_raise_state_identity
- (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
-
-
-#if ( __MigTypeCheck )
-#if __MIG_check__Request__mach_exc_subsystem__
-#if !defined(__MIG_check__Request__mach_exception_raise_t__defined)
-#define __MIG_check__Request__mach_exception_raise_t__defined
-
-mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_t(__attribute__((__unused__)) __Request__mach_exception_raise_t *In0P)
-{
-
- typedef __Request__mach_exception_raise_t __Request;
-#if __MigTypeCheck
- unsigned int msgh_size;
-#endif /* __MigTypeCheck */
-
-#if __MigTypeCheck
- msgh_size = In0P->Head.msgh_size;
- if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
- (In0P->msgh_body.msgh_descriptor_count != 2) ||
- (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 16)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
- return MIG_BAD_ARGUMENTS;
-#endif /* __MigTypeCheck */
-
-#if __MigTypeCheck
- if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR ||
- In0P->thread.disposition != 17)
- return MIG_TYPE_ERROR;
-#endif /* __MigTypeCheck */
-
-#if __MigTypeCheck
- if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR ||
- In0P->task.disposition != 17)
- return MIG_TYPE_ERROR;
-#endif /* __MigTypeCheck */
-
-#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined)
- if (In0P->NDR.int_rep != NDR_record.int_rep)
- __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
-#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_t__codeCnt__defined */
-#if __MigTypeCheck
- if ( In0P->codeCnt > 2 )
- return MIG_BAD_ARGUMENTS;
- if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 16)) / 8 < In0P->codeCnt) ||
- (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 16) + (8 * In0P->codeCnt)))
- return MIG_BAD_ARGUMENTS;
-#endif /* __MigTypeCheck */
-
- return MACH_MSG_SUCCESS;
-}
-#endif /* !defined(__MIG_check__Request__mach_exception_raise_t__defined) */
-#endif /* __MIG_check__Request__mach_exc_subsystem__ */
-#endif /* ( __MigTypeCheck ) */
-
-
-/* Routine mach_exception_raise */
-mig_internal novalue _Xmach_exception_raise
- (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
-{
-
-#ifdef __MigPackStructs
-#pragma pack(4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_port_descriptor_t thread;
- mach_msg_port_descriptor_t task;
- /* end of the kernel processed data */
- NDR_record_t NDR;
- exception_type_t exception;
- mach_msg_type_number_t codeCnt;
- int64_t code[2];
- mach_msg_trailer_t trailer;
- } Request __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack()
-#endif
- typedef __Request__mach_exception_raise_t __Request;
- typedef __Reply__mach_exception_raise_t Reply __attribute__((unused));
-
- /*
- * typedef struct {
- * mach_msg_header_t Head;
- * NDR_record_t NDR;
- * kern_return_t RetCode;
- * } mig_reply_error_t;
- */
-
- Request *In0P = (Request *) InHeadP;
- Reply *OutP = (Reply *) OutHeadP;
-#ifdef __MIG_check__Request__mach_exception_raise_t__defined
- kern_return_t check_result;
-#endif /* __MIG_check__Request__mach_exception_raise_t__defined */
-
- __DeclareRcvRpc(2405, "mach_exception_raise")
- __BeforeRcvRpc(2405, "mach_exception_raise")
-
-#if defined(__MIG_check__Request__mach_exception_raise_t__defined)
- check_result = __MIG_check__Request__mach_exception_raise_t((__Request *)In0P);
- if (check_result != MACH_MSG_SUCCESS)
- { MIG_RETURN_ERROR(OutP, check_result); }
-#endif /* defined(__MIG_check__Request__mach_exception_raise_t__defined) */
-
- OutP->RetCode = catch_mach_exception_raise(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt);
-
- OutP->NDR = NDR_record;
-
-
- __AfterRcvRpc(2405, "mach_exception_raise")
-}
-
-#if ( __MigTypeCheck )
-#if __MIG_check__Request__mach_exc_subsystem__
-#if !defined(__MIG_check__Request__mach_exception_raise_state_t__defined)
-#define __MIG_check__Request__mach_exception_raise_state_t__defined
-
-mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_t **In1PP)
-{
-
- typedef __Request__mach_exception_raise_state_t __Request;
- __Request *In1P;
-#if __MigTypeCheck
- unsigned int msgh_size;
-#endif /* __MigTypeCheck */
- unsigned int msgh_size_delta;
-
-#if __MigTypeCheck
- msgh_size = In0P->Head.msgh_size;
- if ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
- (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
- return MIG_BAD_ARGUMENTS;
-#endif /* __MigTypeCheck */
-
-#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined)
- if (In0P->NDR.int_rep != NDR_record.int_rep)
- __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
-#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__codeCnt__defined */
- msgh_size_delta = (8 * In0P->codeCnt);
-#if __MigTypeCheck
- if ( In0P->codeCnt > 2 )
- return MIG_BAD_ARGUMENTS;
- if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) ||
- (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt)))
- return MIG_BAD_ARGUMENTS;
- msgh_size -= msgh_size_delta;
-#endif /* __MigTypeCheck */
-
- *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16);
-
-#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined)
- if (In0P->NDR.int_rep != NDR_record.int_rep)
- __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep);
-#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_t__old_stateCnt__defined */
-#if __MigTypeCheck
- if ( In1P->old_stateCnt > 224 )
- return MIG_BAD_ARGUMENTS;
- if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) ||
- (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt)))
- return MIG_BAD_ARGUMENTS;
-#endif /* __MigTypeCheck */
-
- return MACH_MSG_SUCCESS;
-}
-#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */
-#endif /* __MIG_check__Request__mach_exc_subsystem__ */
-#endif /* ( __MigTypeCheck ) */
-
-
-/* Routine mach_exception_raise_state */
-mig_internal novalue _Xmach_exception_raise_state
- (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
-{
-
-#ifdef __MigPackStructs
-#pragma pack(4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- exception_type_t exception;
- mach_msg_type_number_t codeCnt;
- int64_t code[2];
- int flavor;
- mach_msg_type_number_t old_stateCnt;
- natural_t old_state[224];
- mach_msg_trailer_t trailer;
- } Request __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack()
-#endif
- typedef __Request__mach_exception_raise_state_t __Request;
- typedef __Reply__mach_exception_raise_state_t Reply __attribute__((unused));
-
- /*
- * typedef struct {
- * mach_msg_header_t Head;
- * NDR_record_t NDR;
- * kern_return_t RetCode;
- * } mig_reply_error_t;
- */
-
- Request *In0P = (Request *) InHeadP;
- Request *In1P;
- Reply *OutP = (Reply *) OutHeadP;
-#ifdef __MIG_check__Request__mach_exception_raise_state_t__defined
- kern_return_t check_result;
-#endif /* __MIG_check__Request__mach_exception_raise_state_t__defined */
-
- __DeclareRcvRpc(2406, "mach_exception_raise_state")
- __BeforeRcvRpc(2406, "mach_exception_raise_state")
-
-#if defined(__MIG_check__Request__mach_exception_raise_state_t__defined)
- check_result = __MIG_check__Request__mach_exception_raise_state_t((__Request *)In0P, (__Request **)&In1P);
- if (check_result != MACH_MSG_SUCCESS)
- { MIG_RETURN_ERROR(OutP, check_result); }
-#endif /* defined(__MIG_check__Request__mach_exception_raise_state_t__defined) */
-
- OutP->new_stateCnt = 224;
-
- OutP->RetCode = catch_mach_exception_raise_state(In0P->Head.msgh_request_port, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt);
- if (OutP->RetCode != KERN_SUCCESS) {
- MIG_RETURN_ERROR(OutP, OutP->RetCode);
- }
-
- OutP->NDR = NDR_record;
-
-
- OutP->flavor = In1P->flavor;
- OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt)));
-
- __AfterRcvRpc(2406, "mach_exception_raise_state")
-}
-
-#if ( __MigTypeCheck )
-#if __MIG_check__Request__mach_exc_subsystem__
-#if !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined)
-#define __MIG_check__Request__mach_exception_raise_state_identity_t__defined
-
-mig_internal kern_return_t __MIG_check__Request__mach_exception_raise_state_identity_t(__attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t *In0P, __attribute__((__unused__)) __Request__mach_exception_raise_state_identity_t **In1PP)
-{
-
- typedef __Request__mach_exception_raise_state_identity_t __Request;
- __Request *In1P;
-#if __MigTypeCheck
- unsigned int msgh_size;
-#endif /* __MigTypeCheck */
- unsigned int msgh_size_delta;
-
-#if __MigTypeCheck
- msgh_size = In0P->Head.msgh_size;
- if (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
- (In0P->msgh_body.msgh_descriptor_count != 2) ||
- (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912)) || (msgh_size > (mach_msg_size_t)sizeof(__Request)))
- return MIG_BAD_ARGUMENTS;
-#endif /* __MigTypeCheck */
-
-#if __MigTypeCheck
- if (In0P->thread.type != MACH_MSG_PORT_DESCRIPTOR ||
- In0P->thread.disposition != 17)
- return MIG_TYPE_ERROR;
-#endif /* __MigTypeCheck */
-
-#if __MigTypeCheck
- if (In0P->task.type != MACH_MSG_PORT_DESCRIPTOR ||
- In0P->task.disposition != 17)
- return MIG_TYPE_ERROR;
-#endif /* __MigTypeCheck */
-
-#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined)
- if (In0P->NDR.int_rep != NDR_record.int_rep)
- __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt(&In0P->codeCnt, In0P->NDR.int_rep);
-#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__codeCnt__defined */
- msgh_size_delta = (8 * In0P->codeCnt);
-#if __MigTypeCheck
- if ( In0P->codeCnt > 2 )
- return MIG_BAD_ARGUMENTS;
- if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 8 < In0P->codeCnt) ||
- (msgh_size < (mach_msg_size_t)(sizeof(__Request) - 912) + (8 * In0P->codeCnt)))
- return MIG_BAD_ARGUMENTS;
- msgh_size -= msgh_size_delta;
-#endif /* __MigTypeCheck */
-
- *In1PP = In1P = (__Request *) ((pointer_t) In0P + msgh_size_delta - 16);
-
-#if defined(__NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined)
- if (In0P->NDR.int_rep != NDR_record.int_rep)
- __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt(&In1P->old_stateCnt, In1P->NDR.int_rep);
-#endif /* __NDR_convert__int_rep__Request__mach_exception_raise_state_identity_t__old_stateCnt__defined */
-#if __MigTypeCheck
- if ( In1P->old_stateCnt > 224 )
- return MIG_BAD_ARGUMENTS;
- if (((msgh_size - (mach_msg_size_t)(sizeof(__Request) - 912)) / 4 < In1P->old_stateCnt) ||
- (msgh_size != (mach_msg_size_t)(sizeof(__Request) - 912) + (4 * In1P->old_stateCnt)))
- return MIG_BAD_ARGUMENTS;
-#endif /* __MigTypeCheck */
-
- return MACH_MSG_SUCCESS;
-}
-#endif /* !defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */
-#endif /* __MIG_check__Request__mach_exc_subsystem__ */
-#endif /* ( __MigTypeCheck ) */
-
-
-/* Routine mach_exception_raise_state_identity */
-mig_internal novalue _Xmach_exception_raise_state_identity
- (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
-{
-
-#ifdef __MigPackStructs
-#pragma pack(4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_port_descriptor_t thread;
- mach_msg_port_descriptor_t task;
- /* end of the kernel processed data */
- NDR_record_t NDR;
- exception_type_t exception;
- mach_msg_type_number_t codeCnt;
- int64_t code[2];
- int flavor;
- mach_msg_type_number_t old_stateCnt;
- natural_t old_state[224];
- mach_msg_trailer_t trailer;
- } Request __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack()
-#endif
- typedef __Request__mach_exception_raise_state_identity_t __Request;
- typedef __Reply__mach_exception_raise_state_identity_t Reply __attribute__((unused));
-
- /*
- * typedef struct {
- * mach_msg_header_t Head;
- * NDR_record_t NDR;
- * kern_return_t RetCode;
- * } mig_reply_error_t;
- */
-
- Request *In0P = (Request *) InHeadP;
- Request *In1P;
- Reply *OutP = (Reply *) OutHeadP;
-#ifdef __MIG_check__Request__mach_exception_raise_state_identity_t__defined
- kern_return_t check_result;
-#endif /* __MIG_check__Request__mach_exception_raise_state_identity_t__defined */
-
- __DeclareRcvRpc(2407, "mach_exception_raise_state_identity")
- __BeforeRcvRpc(2407, "mach_exception_raise_state_identity")
-
-#if defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined)
- check_result = __MIG_check__Request__mach_exception_raise_state_identity_t((__Request *)In0P, (__Request **)&In1P);
- if (check_result != MACH_MSG_SUCCESS)
- { MIG_RETURN_ERROR(OutP, check_result); }
-#endif /* defined(__MIG_check__Request__mach_exception_raise_state_identity_t__defined) */
-
- OutP->new_stateCnt = 224;
-
- OutP->RetCode = catch_mach_exception_raise_state_identity(In0P->Head.msgh_request_port, In0P->thread.name, In0P->task.name, In0P->exception, In0P->code, In0P->codeCnt, &In1P->flavor, In1P->old_state, In1P->old_stateCnt, OutP->new_state, &OutP->new_stateCnt);
- if (OutP->RetCode != KERN_SUCCESS) {
- MIG_RETURN_ERROR(OutP, OutP->RetCode);
- }
-
- OutP->NDR = NDR_record;
-
-
- OutP->flavor = In1P->flavor;
- OutP->Head.msgh_size = (mach_msg_size_t)(sizeof(Reply) - 896) + (((4 * OutP->new_stateCnt)));
-
- __AfterRcvRpc(2407, "mach_exception_raise_state_identity")
-}
-
-
-
-/* Description of this subsystem, for use in direct RPC */
-const struct catch_mach_exc_subsystem catch_mach_exc_subsystem = {
- mach_exc_server_routine,
- 2405,
- 2408,
- (mach_msg_size_t)sizeof(union __ReplyUnion__catch_mach_exc_subsystem),
- (vm_address_t)0,
- {
- { (mig_impl_routine_t) 0,
- (mig_stub_routine_t) _Xmach_exception_raise, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_t)},
- { (mig_impl_routine_t) 0,
- (mig_stub_routine_t) _Xmach_exception_raise_state, 9, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_t)},
- { (mig_impl_routine_t) 0,
- (mig_stub_routine_t) _Xmach_exception_raise_state_identity, 11, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__mach_exception_raise_state_identity_t)},
- }
-};
-
-mig_external boolean_t mach_exc_server
- (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
-{
- /*
- * typedef struct {
- * mach_msg_header_t Head;
- * NDR_record_t NDR;
- * kern_return_t RetCode;
- * } mig_reply_error_t;
- */
-
- register mig_routine_t routine;
-
- OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);
- OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;
- /* Minimal size: routine() will update it if different */
- OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
- OutHeadP->msgh_local_port = MACH_PORT_NULL;
- OutHeadP->msgh_id = InHeadP->msgh_id + 100;
- OutHeadP->msgh_reserved = 0;
-
- if ((InHeadP->msgh_id > 2407) || (InHeadP->msgh_id < 2405) ||
- ((routine = catch_mach_exc_subsystem.routine[InHeadP->msgh_id - 2405].stub_routine) == 0)) {
- ((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;
- ((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;
- return FALSE;
- }
- (*routine) (InHeadP, OutHeadP);
- return TRUE;
-}
-
-mig_external mig_routine_t mach_exc_server_routine
- (mach_msg_header_t *InHeadP)
-{
- register int msgh_id;
-
- msgh_id = InHeadP->msgh_id - 2405;
-
- if ((msgh_id > 2) || (msgh_id < 0))
- return 0;
-
- return catch_mach_exc_subsystem.routine[msgh_id].stub_routine;
-}
-
-#endif
diff --git a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h b/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h
deleted file mode 100644
index 52e53ae..0000000
--- a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/mach_excServer.h
+++ /dev/null
@@ -1,321 +0,0 @@
-#ifndef _mach_exc_server_
-#define _mach_exc_server_
-
-/* Module mach_exc */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* BEGIN VOUCHER CODE */
-
-#ifndef KERNEL
-#if defined(__has_include)
-#if __has_include()
-#ifndef USING_VOUCHERS
-#define USING_VOUCHERS
-#endif
-#ifndef __VOUCHER_FORWARD_TYPE_DECLS__
-#define __VOUCHER_FORWARD_TYPE_DECLS__
-#ifdef __cplusplus
-extern "C" {
-#endif
- extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));
-#ifdef __cplusplus
-}
-#endif
-#endif // __VOUCHER_FORWARD_TYPE_DECLS__
-#endif // __has_include()
-#endif // __has_include
-#endif // !KERNEL
-
-/* END VOUCHER CODE */
-
-
-/* BEGIN MIG_STRNCPY_ZEROFILL CODE */
-
-#if defined(__has_include)
-#if __has_include()
-#ifndef USING_MIG_STRNCPY_ZEROFILL
-#define USING_MIG_STRNCPY_ZEROFILL
-#endif
-#ifndef __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__
-#define __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__
-#ifdef __cplusplus
-extern "C" {
-#endif
- extern int mig_strncpy_zerofill(char *dest, const char *src, int len) __attribute__((weak_import));
-#ifdef __cplusplus
-}
-#endif
-#endif /* __MIG_STRNCPY_ZEROFILL_FORWARD_TYPE_DECLS__ */
-#endif /* __has_include() */
-#endif /* __has_include */
-
-/* END MIG_STRNCPY_ZEROFILL CODE */
-
-
-#ifdef AUTOTEST
-#ifndef FUNCTION_PTR_T
-#define FUNCTION_PTR_T
-typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t);
-typedef struct {
- char *name;
- function_ptr_t function;
-} function_table_entry;
-typedef function_table_entry *function_table_t;
-#endif /* FUNCTION_PTR_T */
-#endif /* AUTOTEST */
-
-#ifndef mach_exc_MSG_COUNT
-#define mach_exc_MSG_COUNT 3
-#endif /* mach_exc_MSG_COUNT */
-
-#include
-#include
-#include
-#include
-
-#ifdef __BeforeMigServerHeader
-__BeforeMigServerHeader
-#endif /* __BeforeMigServerHeader */
-
-
-/* Routine mach_exception_raise */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t catch_mach_exception_raise
-(
- mach_port_t exception_port,
- mach_port_t thread,
- mach_port_t task,
- exception_type_t exception,
- mach_exception_data_t code,
- mach_msg_type_number_t codeCnt
-);
-
-/* Routine mach_exception_raise_state */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t catch_mach_exception_raise_state
-(
- mach_port_t exception_port,
- exception_type_t exception,
- const mach_exception_data_t code,
- mach_msg_type_number_t codeCnt,
- int *flavor,
- const thread_state_t old_state,
- mach_msg_type_number_t old_stateCnt,
- thread_state_t new_state,
- mach_msg_type_number_t *new_stateCnt
-);
-
-/* Routine mach_exception_raise_state_identity */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-kern_return_t catch_mach_exception_raise_state_identity
-(
- mach_port_t exception_port,
- mach_port_t thread,
- mach_port_t task,
- exception_type_t exception,
- mach_exception_data_t code,
- mach_msg_type_number_t codeCnt,
- int *flavor,
- thread_state_t old_state,
- mach_msg_type_number_t old_stateCnt,
- thread_state_t new_state,
- mach_msg_type_number_t *new_stateCnt
-);
-
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-boolean_t mach_exc_server(
- mach_msg_header_t *InHeadP,
- mach_msg_header_t *OutHeadP);
-
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif /* mig_external */
-mig_routine_t mach_exc_server_routine(
- mach_msg_header_t *InHeadP);
-
-
-/* Description of this subsystem, for use in direct RPC */
-extern const struct catch_mach_exc_subsystem {
- mig_server_routine_t server; /* Server routine */
- mach_msg_id_t start; /* Min routine number */
- mach_msg_id_t end; /* Max routine number + 1 */
- unsigned int maxsize; /* Max msg size */
- vm_address_t reserved; /* Reserved */
- struct routine_descriptor /*Array of routine descriptors */
- routine[3];
-} catch_mach_exc_subsystem;
-
-/* typedefs for all requests */
-
-#ifndef __Request__mach_exc_subsystem__defined
-#define __Request__mach_exc_subsystem__defined
-
-#ifdef __MigPackStructs
-#pragma pack(4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_port_descriptor_t thread;
- mach_msg_port_descriptor_t task;
- /* end of the kernel processed data */
- NDR_record_t NDR;
- exception_type_t exception;
- mach_msg_type_number_t codeCnt;
- int64_t code[2];
- } __Request__mach_exception_raise_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack()
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- exception_type_t exception;
- mach_msg_type_number_t codeCnt;
- int64_t code[2];
- int flavor;
- mach_msg_type_number_t old_stateCnt;
- natural_t old_state[224];
- } __Request__mach_exception_raise_state_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack()
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- /* start of the kernel processed data */
- mach_msg_body_t msgh_body;
- mach_msg_port_descriptor_t thread;
- mach_msg_port_descriptor_t task;
- /* end of the kernel processed data */
- NDR_record_t NDR;
- exception_type_t exception;
- mach_msg_type_number_t codeCnt;
- int64_t code[2];
- int flavor;
- mach_msg_type_number_t old_stateCnt;
- natural_t old_state[224];
- } __Request__mach_exception_raise_state_identity_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack()
-#endif
-#endif /* !__Request__mach_exc_subsystem__defined */
-
-
-/* union of all requests */
-
-#ifndef __RequestUnion__catch_mach_exc_subsystem__defined
-#define __RequestUnion__catch_mach_exc_subsystem__defined
-union __RequestUnion__catch_mach_exc_subsystem {
- __Request__mach_exception_raise_t Request_mach_exception_raise;
- __Request__mach_exception_raise_state_t Request_mach_exception_raise_state;
- __Request__mach_exception_raise_state_identity_t Request_mach_exception_raise_state_identity;
-};
-#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */
-/* typedefs for all replies */
-
-#ifndef __Reply__mach_exc_subsystem__defined
-#define __Reply__mach_exc_subsystem__defined
-
-#ifdef __MigPackStructs
-#pragma pack(4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- } __Reply__mach_exception_raise_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack()
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- int flavor;
- mach_msg_type_number_t new_stateCnt;
- natural_t new_state[224];
- } __Reply__mach_exception_raise_state_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack()
-#endif
-
-#ifdef __MigPackStructs
-#pragma pack(4)
-#endif
- typedef struct {
- mach_msg_header_t Head;
- NDR_record_t NDR;
- kern_return_t RetCode;
- int flavor;
- mach_msg_type_number_t new_stateCnt;
- natural_t new_state[224];
- } __Reply__mach_exception_raise_state_identity_t __attribute__((unused));
-#ifdef __MigPackStructs
-#pragma pack()
-#endif
-#endif /* !__Reply__mach_exc_subsystem__defined */
-
-
-/* union of all replies */
-
-#ifndef __ReplyUnion__catch_mach_exc_subsystem__defined
-#define __ReplyUnion__catch_mach_exc_subsystem__defined
-union __ReplyUnion__catch_mach_exc_subsystem {
- __Reply__mach_exception_raise_t Reply_mach_exception_raise;
- __Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state;
- __Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity;
-};
-#endif /* __RequestUnion__catch_mach_exc_subsystem__defined */
-
-#ifndef subsystem_to_name_map_mach_exc
-#define subsystem_to_name_map_mach_exc \
- { "mach_exception_raise", 2405 },\
- { "mach_exception_raise_state", 2406 },\
- { "mach_exception_raise_state_identity", 2407 }
-#endif
-
-#ifdef __AfterMigServerHeader
-__AfterMigServerHeader
-#endif /* __AfterMigServerHeader */
-
-#endif /* _mach_exc_server_ */
diff --git a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift b/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift
deleted file mode 100644
index 91e5d4d..0000000
--- a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// CwlBadInstructionException.swift
-// CwlPreconditionTesting
-//
-// Created by Matt Gallagher on 2016/01/10.
-// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-
-import Foundation
-
-#if SWIFT_PACKAGE
- import CwlMachBadInstructionHandler
-#endif
-
-private func raiseBadInstructionException() {
- BadInstructionException().raise()
-}
-
-/// A simple NSException subclass. It's not required to subclass NSException (since the exception type is represented in the name) but this helps for identifying the exception through runtime type.
-@objc(BadInstructionException)
-public class BadInstructionException: NSException {
- static var name: String = "com.cocoawithlove.BadInstruction"
-
- init() {
- super.init(name: NSExceptionName(rawValue: BadInstructionException.name), reason: nil, userInfo: nil)
- }
-
- required public init?(coder aDecoder: NSCoder) {
- super.init(coder: aDecoder)
- }
-
- /// An Objective-C callable function, invoked from the `mach_exc_server` callback function `catch_mach_exception_raise_state` to push the `raiseBadInstructionException` function onto the stack.
- @objc(receiveReply:)
- public class func receiveReply(_ value: NSValue) -> NSNumber {
- #if arch(x86_64)
- var reply = bad_instruction_exception_reply_t(exception_port: 0, exception: 0, code: nil, codeCnt: 0, flavor: nil, old_state: nil, old_stateCnt: 0, new_state: nil, new_stateCnt: nil)
- withUnsafeMutablePointer(to: &reply) { value.getValue(UnsafeMutableRawPointer($0)) }
-
- let old_state: UnsafePointer = reply.old_state!
- let old_stateCnt: mach_msg_type_number_t = reply.old_stateCnt
- let new_state: thread_state_t = reply.new_state!
- let new_stateCnt: UnsafeMutablePointer = reply.new_stateCnt!
-
- // Make sure we've been given enough memory
- if old_stateCnt != x86_THREAD_STATE64_COUNT || new_stateCnt.pointee < x86_THREAD_STATE64_COUNT {
- return NSNumber(value: KERN_INVALID_ARGUMENT)
- }
-
- // Read the old thread state
- var state = old_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { return $0.pointee }
-
- // 1. Decrement the stack pointer
- state.__rsp -= __uint64_t(MemoryLayout.size)
-
- // 2. Save the old Instruction Pointer to the stack.
- if let pointer = UnsafeMutablePointer<__uint64_t>(bitPattern: UInt(state.__rsp)) {
- pointer.pointee = state.__rip
- } else {
- return NSNumber(value: KERN_INVALID_ARGUMENT)
- }
-
- // 3. Set the Instruction Pointer to the new function's address
- var f: @convention(c) () -> Void = raiseBadInstructionException
- withUnsafePointer(to: &f) {
- state.__rip = $0.withMemoryRebound(to: __uint64_t.self, capacity: 1) { return $0.pointee }
- }
-
- // Write the new thread state
- new_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { $0.pointee = state }
- new_stateCnt.pointee = x86_THREAD_STATE64_COUNT
-
- return NSNumber(value: KERN_SUCCESS)
- #else
- fatalError("Unavailable for this CPU architecture")
- #endif
- }
-}
diff --git a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift b/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift
deleted file mode 100644
index f96ec63..0000000
--- a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlCatchBadInstruction.swift
+++ /dev/null
@@ -1,197 +0,0 @@
-//
-// CwlCatchBadInstruction.swift
-// CwlPreconditionTesting
-//
-// Created by Matt Gallagher on 2016/01/10.
-// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-
-import Foundation
-
-#if SWIFT_PACKAGE
- import CwlMachBadInstructionHandler
-#endif
-
-#if arch(x86_64)
-
- private enum PthreadError: Error { case code(Int32) }
- private enum MachExcServer: Error { case code(kern_return_t) }
-
- /// A quick function for converting Mach error results into Swift errors
- private func kernCheck(_ f: () -> Int32) throws {
- let r = f()
- guard r == KERN_SUCCESS else {
- throw NSError(domain: NSMachErrorDomain, code: Int(r), userInfo: nil)
- }
- }
-
- extension request_mach_exception_raise_t {
- mutating func withMsgHeaderPointer(in block: (UnsafeMutablePointer) -> R) -> R {
- return withUnsafeMutablePointer(to: &self) { p -> R in
- return p.withMemoryRebound(to: mach_msg_header_t.self, capacity: 1) { ptr -> R in
- return block(ptr)
- }
- }
- }
- }
-
- extension reply_mach_exception_raise_state_t {
- mutating func withMsgHeaderPointer(in block: (UnsafeMutablePointer) -> R) -> R {
- return withUnsafeMutablePointer(to: &self) { p -> R in
- return p.withMemoryRebound(to: mach_msg_header_t.self, capacity: 1) { ptr -> R in
- return block(ptr)
- }
- }
- }
- }
-
- /// A structure used to store context associated with the Mach message port
- private struct MachContext {
- var masks = execTypesCountTuple()
- var count: mach_msg_type_number_t = 0
- var ports = execTypesCountTuple()
- var behaviors = execTypesCountTuple()
- var flavors = execTypesCountTuple()
- var currentExceptionPort: mach_port_t = 0
- var handlerThread: pthread_t? = nil
-
- static func internalMutablePointers(_ m: UnsafeMutablePointer>, _ c: UnsafeMutablePointer, _ p: UnsafeMutablePointer>, _ b: UnsafeMutablePointer>, _ f: UnsafeMutablePointer>, _ block: (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> R) -> R {
- return m.withMemoryRebound(to: exception_mask_t.self, capacity: 1) { masksPtr in
- return c.withMemoryRebound(to: mach_msg_type_number_t.self, capacity: 1) { countPtr in
- return p.withMemoryRebound(to: mach_port_t.self, capacity: 1) { portsPtr in
- return b.withMemoryRebound(to: exception_behavior_t.self, capacity: 1) { behaviorsPtr in
- return f.withMemoryRebound(to: thread_state_flavor_t.self, capacity: 1) { flavorsPtr in
- return block(masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr)
- }
- }
- }
- }
- }
- }
-
- mutating func withUnsafeMutablePointers(in block: @escaping (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> R) -> R {
- return MachContext.internalMutablePointers(&masks, &count, &ports, &behaviors, &flavors, block)
- }
- }
-
- /// A function for receiving mach messages and parsing the first with mach_exc_server (and if any others are received, throwing them away).
- private func machMessageHandler(_ arg: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
- let context = arg.assumingMemoryBound(to: MachContext.self).pointee
- var request = request_mach_exception_raise_t()
- var reply = reply_mach_exception_raise_state_t()
-
- var handledfirstException = false
- repeat { do {
- // Request the next mach message from the port
- request.Head.msgh_local_port = context.currentExceptionPort
- request.Head.msgh_size = UInt32(MemoryLayout.size)
- let requestSize = request.Head.msgh_size
- try kernCheck { request.withMsgHeaderPointer { requestPtr in
- mach_msg(requestPtr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0, requestSize, context.currentExceptionPort, 0, UInt32(MACH_PORT_NULL))
- } }
-
- // Prepare the reply structure
- reply.Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.Head.msgh_bits), 0)
- reply.Head.msgh_local_port = UInt32(MACH_PORT_NULL)
- reply.Head.msgh_remote_port = request.Head.msgh_remote_port
- reply.Head.msgh_size = UInt32(MemoryLayout.size)
- reply.NDR = NDR_record
-
- if !handledfirstException {
- // Use the MiG generated server to invoke our handler for the request and fill in the rest of the reply structure
- guard request.withMsgHeaderPointer(in: { requestPtr in reply.withMsgHeaderPointer { replyPtr in
- mach_exc_server(requestPtr, replyPtr)
- } }) != 0 else { throw MachExcServer.code(reply.RetCode) }
-
- handledfirstException = true
- } else {
- // If multiple fatal errors occur, don't handle subsquent errors (let the program crash)
- reply.RetCode = KERN_FAILURE
- }
-
- // Send the reply
- let replySize = reply.Head.msgh_size
- try kernCheck { reply.withMsgHeaderPointer { replyPtr in
- mach_msg(replyPtr, MACH_SEND_MSG, replySize, 0, UInt32(MACH_PORT_NULL), 0, UInt32(MACH_PORT_NULL))
- } }
- } catch let error as NSError where (error.domain == NSMachErrorDomain && (error.code == Int(MACH_RCV_PORT_CHANGED) || error.code == Int(MACH_RCV_INVALID_NAME))) {
- // Port was already closed before we started or closed while we were listening.
- // This means the controlling thread shut down.
- return nil
- } catch {
- // Should never be reached but this is testing code, don't try to recover, just abort
- fatalError("Mach message error: \(error)")
- } } while true
- }
-
- /// Run the provided block. If a mach "BAD_INSTRUCTION" exception is raised, catch it and return a BadInstructionException (which captures stack information about the throw site, if desired). Otherwise return nil.
- /// NOTE: This function is only intended for use in test harnesses – use in a distributed build is almost certainly a bad choice. If a "BAD_INSTRUCTION" exception is raised, the block will be exited before completion via Objective-C exception. The risks associated with an Objective-C exception apply here: most Swift/Objective-C functions are *not* exception-safe. Memory may be leaked and the program will not necessarily be left in a safe state.
- /// - parameter block: a function without parameters that will be run
- /// - returns: if an EXC_BAD_INSTRUCTION is raised during the execution of `block` then a BadInstructionException will be returned, otherwise `nil`.
- public func catchBadInstruction(in block: () -> Void) -> BadInstructionException? {
- var context = MachContext()
- var result: BadInstructionException? = nil
- do {
- var handlerThread: pthread_t? = nil
- defer {
- // 8. Wait for the thread to terminate *if* we actually made it to the creation point
- // The mach port should be destroyed *before* calling pthread_join to avoid a deadlock.
- if handlerThread != nil {
- pthread_join(handlerThread!, nil)
- }
- }
-
- try kernCheck {
- // 1. Create the mach port
- mach_port_allocate(mach_task_self_, MACH_PORT_RIGHT_RECEIVE, &context.currentExceptionPort)
- }
- defer {
- // 7. Cleanup the mach port
- mach_port_destroy(mach_task_self_, context.currentExceptionPort)
- }
-
- try kernCheck {
- // 2. Configure the mach port
- mach_port_insert_right(mach_task_self_, context.currentExceptionPort, context.currentExceptionPort, MACH_MSG_TYPE_MAKE_SEND)
- }
-
- let currentExceptionPtr = context.currentExceptionPort
- try kernCheck { context.withUnsafeMutablePointers { masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr in
- // 3. Apply the mach port as the handler for this thread
- thread_swap_exception_ports(mach_thread_self(), EXC_MASK_BAD_INSTRUCTION, currentExceptionPtr, Int32(bitPattern: UInt32(EXCEPTION_STATE) | MACH_EXCEPTION_CODES), x86_THREAD_STATE64, masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr)
- } }
-
- defer { context.withUnsafeMutablePointers { masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr in
- // 6. Unapply the mach port
- _ = thread_swap_exception_ports(mach_thread_self(), EXC_MASK_BAD_INSTRUCTION, 0, EXCEPTION_DEFAULT, THREAD_STATE_NONE, masksPtr, countPtr, portsPtr, behaviorsPtr, flavorsPtr)
- } }
-
- try withUnsafeMutablePointer(to: &context) { c throws in
- // 4. Create the thread
- let e = pthread_create(&handlerThread, nil, machMessageHandler, c)
- guard e == 0 else { throw PthreadError.code(e) }
-
- // 5. Run the block
- result = BadInstructionException.catchException(in: block)
- }
- } catch {
- // Should never be reached but this is testing code, don't try to recover, just abort
- fatalError("Mach port error: \(error)")
- }
- return result
- }
-
-#endif
-
diff --git a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift b/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift
deleted file mode 100644
index 8d99d5e..0000000
--- a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// CwlDarwinDefinitions.swift
-// CwlPreconditionTesting
-//
-// Created by Matt Gallagher on 2016/01/10.
-// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-
-import Darwin
-
-#if arch(x86_64)
-
- // From /usr/include/mach/message.h
- // #define MACH_MSG_TYPE_MAKE_SEND 20 /* Must hold receive right */
- // #define MACH_MSGH_BITS_REMOTE(bits) \
- // ((bits) & MACH_MSGH_BITS_REMOTE_MASK)
- // #define MACH_MSGH_BITS(remote, local) /* legacy */ \
- // ((remote) | ((local) << 8))
- public let MACH_MSG_TYPE_MAKE_SEND: UInt32 = 20
- public func MACH_MSGH_BITS_REMOTE(_ bits: UInt32) -> UInt32 { return bits & UInt32(MACH_MSGH_BITS_REMOTE_MASK) }
- public func MACH_MSGH_BITS(_ remote: UInt32, _ local: UInt32) -> UInt32 { return ((remote) | ((local) << 8)) }
-
- // From /usr/include/mach/exception_types.h
- // #define EXC_BAD_INSTRUCTION 2 /* Instruction failed */
- // #define EXC_MASK_BAD_INSTRUCTION (1 << EXC_BAD_INSTRUCTION)
- public let EXC_BAD_INSTRUCTION: UInt32 = 2
- public let EXC_MASK_BAD_INSTRUCTION: UInt32 = 1 << EXC_BAD_INSTRUCTION
-
- // From /usr/include/mach/i386/thread_status.h
- // #define x86_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \
- // ( sizeof (x86_thread_state64_t) / sizeof (int) ))
- public let x86_THREAD_STATE64_COUNT = UInt32(MemoryLayout.size / MemoryLayout.size)
-
- public let EXC_TYPES_COUNT = 14
- public struct execTypesCountTuple {
- // From /usr/include/mach/i386/exception.h
- // #define EXC_TYPES_COUNT 14 /* incl. illegal exception 0 */
- public var value: (T, T, T, T, T, T, T, T, T, T, T, T, T, T) = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
- public init() {
- }
- }
-
-#endif
diff --git a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h b/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h
deleted file mode 100644
index 7c50da1..0000000
--- a/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// CwlPreconditionTesting.h
-// CwlPreconditionTesting
-//
-// Created by Matt Gallagher on 2016/01/10.
-// Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-
-#import
-
-extern bool _swift_reportFatalErrorsToDebugger;
-
-//! Project version number for CwlUtils.
-FOUNDATION_EXPORT double CwlPreconditionTestingVersionNumber;
-
-//! Project version string for CwlUtils.
-FOUNDATION_EXPORT const unsigned char CwlAssertingTestingVersionString[];
-
-#include "CwlMachBadInstructionHandler.h"
-#include "CwlCatchException.h"
diff --git a/Pods/Nimble/LICENSE b/Pods/Nimble/LICENSE
deleted file mode 100644
index 82b84bf..0000000
--- a/Pods/Nimble/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
-Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "{}"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright 2016 Quick Team
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/Pods/Nimble/README.md b/Pods/Nimble/README.md
deleted file mode 100644
index 4f7f89b..0000000
--- a/Pods/Nimble/README.md
+++ /dev/null
@@ -1,1772 +0,0 @@
-# Nimble
-
-[![Build Status](https://travis-ci.org/Quick/Nimble.svg?branch=master)](https://travis-ci.org/Quick/Nimble)
-[![CocoaPods](https://img.shields.io/cocoapods/v/Nimble.svg)](https://cocoapods.org/pods/Nimble)
-[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
-[![Accio supported](https://img.shields.io/badge/Accio-supported-0A7CF5.svg?style=flat)](https://github.com/JamitLabs/Accio)
-[![Platforms](https://img.shields.io/cocoapods/p/Nimble.svg)](https://cocoapods.org/pods/Nimble)
-[![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com)
-
-Use Nimble to express the expected outcomes of Swift
-or Objective-C expressions. Inspired by
-[Cedar](https://github.com/pivotal/cedar).
-
-```swift
-// Swift
-expect(1 + 1).to(equal(2))
-expect(1.2).to(beCloseTo(1.1, within: 0.1))
-expect(3) > 2
-expect("seahorse").to(contain("sea"))
-expect(["Atlantic", "Pacific"]).toNot(contain("Mississippi"))
-expect(ocean.isClean).toEventually(beTruthy())
-```
-
-# How to Use Nimble
-
-
-
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Some Background: Expressing Outcomes Using Assertions in XCTest](#some-background-expressing-outcomes-using-assertions-in-xctest)
-- [Nimble: Expectations Using `expect(...).to`](#nimble-expectations-using-expectto)
- - [Custom Failure Messages](#custom-failure-messages)
- - [Type Safety](#type-safety)
- - [Operator Overloads](#operator-overloads)
- - [Lazily Computed Values](#lazily-computed-values)
- - [C Primitives](#c-primitives)
- - [Asynchronous Expectations](#asynchronous-expectations)
- - [Objective-C Support](#objective-c-support)
- - [Disabling Objective-C Shorthand](#disabling-objective-c-shorthand)
-- [Built-in Matcher Functions](#built-in-matcher-functions)
- - [Type Checking](#type-checking)
- - [Equivalence](#equivalence)
- - [Identity](#identity)
- - [Comparisons](#comparisons)
- - [Types/Classes](#typesclasses)
- - [Truthiness](#truthiness)
- - [Swift Assertions](#swift-assertions)
- - [Swift Error Handling](#swift-error-handling)
- - [Exceptions](#exceptions)
- - [Collection Membership](#collection-membership)
- - [Strings](#strings)
- - [Collection Elements](#collection-elements)
- - [Collection Count](#collection-count)
- - [Notifications](#notifications)
- - [Matching a value to any of a group of matchers](#matching-a-value-to-any-of-a-group-of-matchers)
- - [Custom Validation](#custom-validation)
-- [Writing Your Own Matchers](#writing-your-own-matchers)
- - [PredicateResult](#predicateresult)
- - [Lazy Evaluation](#lazy-evaluation)
- - [Type Checking via Swift Generics](#type-checking-via-swift-generics)
- - [Customizing Failure Messages](#customizing-failure-messages)
- - [Basic Customization](#basic-customization)
- - [Full Customization](#full-customization)
- - [Supporting Objective-C](#supporting-objective-c)
- - [Properly Handling `nil` in Objective-C Matchers](#properly-handling-nil-in-objective-c-matchers)
- - [Migrating from the Old Matcher API](#migrating-from-the-old-matcher-api)
- - [Minimal Step - Use `.predicate`](#minimal-step---use-predicate)
- - [Convert to use `Predicate` Type with Old Matcher Constructor](#convert-to-use-predicate-type-with-old-matcher-constructor)
- - [Convert to `Predicate` Type with Preferred Constructor](#convert-to-predicate-type-with-preferred-constructor)
- - [Deprecation Roadmap](#deprecation-roadmap)
-- [Installing Nimble](#installing-nimble)
- - [Installing Nimble as a Submodule](#installing-nimble-as-a-submodule)
- - [Installing Nimble via CocoaPods](#installing-nimble-via-cocoapods)
- - [Installing Nimble via Accio](#installing-nimble-via-accio)
- - [Using Nimble without XCTest](#using-nimble-without-xctest)
-
-
-
-# Some Background: Expressing Outcomes Using Assertions in XCTest
-
-Apple's Xcode includes the XCTest framework, which provides
-assertion macros to test whether code behaves properly.
-For example, to assert that `1 + 1 = 2`, XCTest has you write:
-
-```swift
-// Swift
-
-XCTAssertEqual(1 + 1, 2, "expected one plus one to equal two")
-```
-
-Or, in Objective-C:
-
-```objc
-// Objective-C
-
-XCTAssertEqual(1 + 1, 2, @"expected one plus one to equal two");
-```
-
-XCTest assertions have a couple of drawbacks:
-
-1. **Not enough macros.** There's no easy way to assert that a string
- contains a particular substring, or that a number is less than or
- equal to another.
-2. **It's hard to write asynchronous tests.** XCTest forces you to write
- a lot of boilerplate code.
-
-Nimble addresses these concerns.
-
-# Nimble: Expectations Using `expect(...).to`
-
-Nimble allows you to express expectations using a natural,
-easily understood language:
-
-```swift
-// Swift
-
-import Nimble
-
-expect(seagull.squawk).to(equal("Squee!"))
-```
-
-```objc
-// Objective-C
-
-@import Nimble;
-
-expect(seagull.squawk).to(equal(@"Squee!"));
-```
-
-> The `expect` function autocompletes to include `file:` and `line:`,
- but these parameters are optional. Use the default values to have
- Xcode highlight the correct line when an expectation is not met.
-
-To perform the opposite expectation--to assert something is *not*
-equal--use `toNot` or `notTo`:
-
-```swift
-// Swift
-
-import Nimble
-
-expect(seagull.squawk).toNot(equal("Oh, hello there!"))
-expect(seagull.squawk).notTo(equal("Oh, hello there!"))
-```
-
-```objc
-// Objective-C
-
-@import Nimble;
-
-expect(seagull.squawk).toNot(equal(@"Oh, hello there!"));
-expect(seagull.squawk).notTo(equal(@"Oh, hello there!"));
-```
-
-## Custom Failure Messages
-
-Would you like to add more information to the test's failure messages? Use the `description` optional argument to add your own text:
-
-```swift
-// Swift
-
-expect(1 + 1).to(equal(3))
-// failed - expected to equal <3>, got <2>
-
-expect(1 + 1).to(equal(3), description: "Make sure libKindergartenMath is loaded")
-// failed - Make sure libKindergartenMath is loaded
-// expected to equal <3>, got <2>
-```
-
-Or the *WithDescription version in Objective-C:
-
-```objc
-// Objective-C
-
-@import Nimble;
-
-expect(@(1+1)).to(equal(@3));
-// failed - expected to equal <3.0000>, got <2.0000>
-
-expect(@(1+1)).toWithDescription(equal(@3), @"Make sure libKindergartenMath is loaded");
-// failed - Make sure libKindergartenMath is loaded
-// expected to equal <3.0000>, got <2.0000>
-```
-
-## Type Safety
-
-Nimble makes sure you don't compare two types that don't match:
-
-```swift
-// Swift
-
-// Does not compile:
-expect(1 + 1).to(equal("Squee!"))
-```
-
-> Nimble uses generics--only available in Swift--to ensure
- type correctness. That means type checking is
- not available when using Nimble in Objective-C. :sob:
-
-## Operator Overloads
-
-Tired of so much typing? With Nimble, you can use overloaded operators
-like `==` for equivalence, or `>` for comparisons:
-
-```swift
-// Swift
-
-// Passes if squawk does not equal "Hi!":
-expect(seagull.squawk) != "Hi!"
-
-// Passes if 10 is greater than 2:
-expect(10) > 2
-```
-
-> Operator overloads are only available in Swift, so you won't be able
- to use this syntax in Objective-C. :broken_heart:
-
-## Lazily Computed Values
-
-The `expect` function doesn't evaluate the value it's given until it's
-time to match. So Nimble can test whether an expression raises an
-exception once evaluated:
-
-```swift
-// Swift
-
-// Note: Swift currently doesn't have exceptions.
-// Only Objective-C code can raise exceptions
-// that Nimble will catch.
-// (see https://github.com/Quick/Nimble/issues/220#issuecomment-172667064)
-let exception = NSException(
- name: NSInternalInconsistencyException,
- reason: "Not enough fish in the sea.",
- userInfo: ["something": "is fishy"])
-expect { exception.raise() }.to(raiseException())
-
-// Also, you can customize raiseException to be more specific
-expect { exception.raise() }.to(raiseException(named: NSInternalInconsistencyException))
-expect { exception.raise() }.to(raiseException(
- named: NSInternalInconsistencyException,
- reason: "Not enough fish in the sea"))
-expect { exception.raise() }.to(raiseException(
- named: NSInternalInconsistencyException,
- reason: "Not enough fish in the sea",
- userInfo: ["something": "is fishy"]))
-```
-
-Objective-C works the same way, but you must use the `expectAction`
-macro when making an expectation on an expression that has no return
-value:
-
-```objc
-// Objective-C
-
-NSException *exception = [NSException exceptionWithName:NSInternalInconsistencyException
- reason:@"Not enough fish in the sea."
- userInfo:nil];
-expectAction(^{ [exception raise]; }).to(raiseException());
-
-// Use the property-block syntax to be more specific.
-expectAction(^{ [exception raise]; }).to(raiseException().named(NSInternalInconsistencyException));
-expectAction(^{ [exception raise]; }).to(raiseException().
- named(NSInternalInconsistencyException).
- reason("Not enough fish in the sea"));
-expectAction(^{ [exception raise]; }).to(raiseException().
- named(NSInternalInconsistencyException).
- reason("Not enough fish in the sea").
- userInfo(@{@"something": @"is fishy"}));
-
-// You can also pass a block for custom matching of the raised exception
-expectAction(exception.raise()).to(raiseException().satisfyingBlock(^(NSException *exception) {
- expect(exception.name).to(beginWith(NSInternalInconsistencyException));
-}));
-```
-
-## C Primitives
-
-Some testing frameworks make it hard to test primitive C values.
-In Nimble, it just works:
-
-```swift
-// Swift
-
-let actual: CInt = 1
-let expectedValue: CInt = 1
-expect(actual).to(equal(expectedValue))
-```
-
-In fact, Nimble uses type inference, so you can write the above
-without explicitly specifying both types:
-
-```swift
-// Swift
-
-expect(1 as CInt).to(equal(1))
-```
-
-> In Objective-C, Nimble only supports Objective-C objects. To
- make expectations on primitive C values, wrap then in an object
- literal:
-
-```objc
-expect(@(1 + 1)).to(equal(@2));
-```
-
-## Asynchronous Expectations
-
-In Nimble, it's easy to make expectations on values that are updated
-asynchronously. Just use `toEventually` or `toEventuallyNot`:
-
-```swift
-// Swift
-DispatchQueue.main.async {
- ocean.add("dolphins")
- ocean.add("whales")
-}
-expect(ocean).toEventually(contain("dolphins", "whales"))
-```
-
-
-```objc
-// Objective-C
-
-dispatch_async(dispatch_get_main_queue(), ^{
- [ocean add:@"dolphins"];
- [ocean add:@"whales"];
-});
-expect(ocean).toEventually(contain(@"dolphins", @"whales"));
-```
-
-Note: toEventually triggers its polls on the main thread. Blocking the main
-thread will cause Nimble to stop the run loop. This can cause test pollution
-for whatever incomplete code that was running on the main thread. Blocking the
-main thread can be caused by blocking IO, calls to sleep(), deadlocks, and
-synchronous IPC.
-
-In the above example, `ocean` is constantly re-evaluated. If it ever
-contains dolphins and whales, the expectation passes. If `ocean` still
-doesn't contain them, even after being continuously re-evaluated for one
-whole second, the expectation fails.
-
-Sometimes it takes more than a second for a value to update. In those
-cases, use the `timeout` parameter:
-
-```swift
-// Swift
-
-// Waits three seconds for ocean to contain "starfish":
-expect(ocean).toEventually(contain("starfish"), timeout: 3)
-
-// Evaluate someValue every 0.2 seconds repeatedly until it equals 100, or fails if it timeouts after 5.5 seconds.
-expect(someValue).toEventually(equal(100), timeout: 5.5, pollInterval: 0.2)
-```
-
-```objc
-// Objective-C
-
-// Waits three seconds for ocean to contain "starfish":
-expect(ocean).withTimeout(3).toEventually(contain(@"starfish"));
-```
-
-You can also provide a callback by using the `waitUntil` function:
-
-```swift
-// Swift
-
-waitUntil { done in
- ocean.goFish { success in
- expect(success).to(beTrue())
- done()
- }
-}
-```
-
-```objc
-// Objective-C
-
-waitUntil(^(void (^done)(void)){
- [ocean goFishWithHandler:^(BOOL success){
- expect(success).to(beTrue());
- done();
- }];
-});
-```
-
-`waitUntil` also optionally takes a timeout parameter:
-
-```swift
-// Swift
-
-waitUntil(timeout: 10) { done in
- ocean.goFish { success in
- expect(success).to(beTrue())
- done()
- }
-}
-```
-
-```objc
-// Objective-C
-
-waitUntilTimeout(10, ^(void (^done)(void)){
- [ocean goFishWithHandler:^(BOOL success){
- expect(success).to(beTrue());
- done();
- }];
-});
-```
-
-Note: `waitUntil` triggers its timeout code on the main thread. Blocking the main
-thread will cause Nimble to stop the run loop to continue. This can cause test
-pollution for whatever incomplete code that was running on the main thread.
-Blocking the main thread can be caused by blocking IO, calls to sleep(),
-deadlocks, and synchronous IPC.
-
-In some cases (e.g. when running on slower machines) it can be useful to modify
-the default timeout and poll interval values. This can be done as follows:
-
-```swift
-// Swift
-
-// Increase the global timeout to 5 seconds:
-Nimble.AsyncDefaults.Timeout = 5
-
-// Slow the polling interval to 0.1 seconds:
-Nimble.AsyncDefaults.PollInterval = 0.1
-```
-
-## Objective-C Support
-
-Nimble has full support for Objective-C. However, there are two things
-to keep in mind when using Nimble in Objective-C:
-
-1. All parameters passed to the `expect` function, as well as matcher
- functions like `equal`, must be Objective-C objects or can be converted into
- an `NSObject` equivalent:
-
- ```objc
- // Objective-C
-
- @import Nimble;
-
- expect(@(1 + 1)).to(equal(@2));
- expect(@"Hello world").to(contain(@"world"));
-
- // Boxed as NSNumber *
- expect(2).to(equal(2));
- expect(1.2).to(beLessThan(2.0));
- expect(true).to(beTruthy());
-
- // Boxed as NSString *
- expect("Hello world").to(equal("Hello world"));
-
- // Boxed as NSRange
- expect(NSMakeRange(1, 10)).to(equal(NSMakeRange(1, 10)));
- ```
-
-2. To make an expectation on an expression that does not return a value,
- such as `-[NSException raise]`, use `expectAction` instead of
- `expect`:
-
- ```objc
- // Objective-C
-
- expectAction(^{ [exception raise]; }).to(raiseException());
- ```
-
-The following types are currently converted to an `NSObject` type:
-
- - **C Numeric types** are converted to `NSNumber *`
- - `NSRange` is converted to `NSValue *`
- - `char *` is converted to `NSString *`
-
-For the following matchers:
-
-- `equal`
-- `beGreaterThan`
-- `beGreaterThanOrEqual`
-- `beLessThan`
-- `beLessThanOrEqual`
-- `beCloseTo`
-- `beTrue`
-- `beFalse`
-- `beTruthy`
-- `beFalsy`
-- `haveCount`
-
-If you would like to see more, [file an issue](https://github.com/Quick/Nimble/issues).
-
-## Disabling Objective-C Shorthand
-
-Nimble provides a shorthand for expressing expectations using the
-`expect` function. To disable this shorthand in Objective-C, define the
-`NIMBLE_DISABLE_SHORT_SYNTAX` macro somewhere in your code before
-importing Nimble:
-
-```objc
-#define NIMBLE_DISABLE_SHORT_SYNTAX 1
-
-@import Nimble;
-
-NMB_expect(^{ return seagull.squawk; }, __FILE__, __LINE__).to(NMB_equal(@"Squee!"));
-```
-
-> Disabling the shorthand is useful if you're testing functions with
- names that conflict with Nimble functions, such as `expect` or
- `equal`. If that's not the case, there's no point in disabling the
- shorthand.
-
-# Built-in Matcher Functions
-
-Nimble includes a wide variety of matcher functions.
-
-## Type Checking
-
-Nimble supports checking the type membership of any kind of object, whether
-Objective-C conformant or not:
-
-```swift
-// Swift
-
-protocol SomeProtocol{}
-class SomeClassConformingToProtocol: SomeProtocol{}
-struct SomeStructConformingToProtocol: SomeProtocol{}
-
-// The following tests pass
-expect(1).to(beAKindOf(Int.self))
-expect("turtle").to(beAKindOf(String.self))
-
-let classObject = SomeClassConformingToProtocol()
-expect(classObject).to(beAKindOf(SomeProtocol.self))
-expect(classObject).to(beAKindOf(SomeClassConformingToProtocol.self))
-expect(classObject).toNot(beAKindOf(SomeStructConformingToProtocol.self))
-
-let structObject = SomeStructConformingToProtocol()
-expect(structObject).to(beAKindOf(SomeProtocol.self))
-expect(structObject).to(beAKindOf(SomeStructConformingToProtocol.self))
-expect(structObject).toNot(beAKindOf(SomeClassConformingToProtocol.self))
-```
-
-```objc
-// Objective-C
-
-// The following tests pass
-NSMutableArray *array = [NSMutableArray array];
-expect(array).to(beAKindOf([NSArray class]));
-expect(@1).toNot(beAKindOf([NSNull class]));
-```
-
-Objects can be tested for their exact types using the `beAnInstanceOf` matcher:
-
-```swift
-// Swift
-
-protocol SomeProtocol{}
-class SomeClassConformingToProtocol: SomeProtocol{}
-struct SomeStructConformingToProtocol: SomeProtocol{}
-
-// Unlike the 'beKindOf' matcher, the 'beAnInstanceOf' matcher only
-// passes if the object is the EXACT type requested. The following
-// tests pass -- note its behavior when working in an inheritance hierarchy.
-expect(1).to(beAnInstanceOf(Int.self))
-expect("turtle").to(beAnInstanceOf(String.self))
-
-let classObject = SomeClassConformingToProtocol()
-expect(classObject).toNot(beAnInstanceOf(SomeProtocol.self))
-expect(classObject).to(beAnInstanceOf(SomeClassConformingToProtocol.self))
-expect(classObject).toNot(beAnInstanceOf(SomeStructConformingToProtocol.self))
-
-let structObject = SomeStructConformingToProtocol()
-expect(structObject).toNot(beAnInstanceOf(SomeProtocol.self))
-expect(structObject).to(beAnInstanceOf(SomeStructConformingToProtocol.self))
-expect(structObject).toNot(beAnInstanceOf(SomeClassConformingToProtocol.self))
-```
-
-## Equivalence
-
-```swift
-// Swift
-
-// Passes if 'actual' is equivalent to 'expected':
-expect(actual).to(equal(expected))
-expect(actual) == expected
-
-// Passes if 'actual' is not equivalent to 'expected':
-expect(actual).toNot(equal(expected))
-expect(actual) != expected
-```
-
-```objc
-// Objective-C
-
-// Passes if 'actual' is equivalent to 'expected':
-expect(actual).to(equal(expected))
-
-// Passes if 'actual' is not equivalent to 'expected':
-expect(actual).toNot(equal(expected))
-```
-
-Values must be `Equatable`, `Comparable`, or subclasses of `NSObject`.
-`equal` will always fail when used to compare one or more `nil` values.
-
-## Identity
-
-```swift
-// Swift
-
-// Passes if 'actual' has the same pointer address as 'expected':
-expect(actual).to(beIdenticalTo(expected))
-expect(actual) === expected
-
-// Passes if 'actual' does not have the same pointer address as 'expected':
-expect(actual).toNot(beIdenticalTo(expected))
-expect(actual) !== expected
-```
-
-It is important to remember that `beIdenticalTo` only makes sense when comparing
-types with reference semantics, which have a notion of identity. In Swift,
-that means types that are defined as a `class`.
-
-This matcher will not work when comparing types with value semantics such as
-those defined as a `struct` or `enum`. If you need to compare two value types,
-consider what it means for instances of your type to be identical. This may mean
-comparing individual properties or, if it makes sense to do so, conforming your type
-to `Equatable` and using Nimble's equivalence matchers instead.
-
-
-```objc
-// Objective-C
-
-// Passes if 'actual' has the same pointer address as 'expected':
-expect(actual).to(beIdenticalTo(expected));
-
-// Passes if 'actual' does not have the same pointer address as 'expected':
-expect(actual).toNot(beIdenticalTo(expected));
-```
-
-## Comparisons
-
-```swift
-// Swift
-
-expect(actual).to(beLessThan(expected))
-expect(actual) < expected
-
-expect(actual).to(beLessThanOrEqualTo(expected))
-expect(actual) <= expected
-
-expect(actual).to(beGreaterThan(expected))
-expect(actual) > expected
-
-expect(actual).to(beGreaterThanOrEqualTo(expected))
-expect(actual) >= expected
-```
-
-```objc
-// Objective-C
-
-expect(actual).to(beLessThan(expected));
-expect(actual).to(beLessThanOrEqualTo(expected));
-expect(actual).to(beGreaterThan(expected));
-expect(actual).to(beGreaterThanOrEqualTo(expected));
-```
-
-> Values given to the comparison matchers above must implement
- `Comparable`.
-
-Because of how computers represent floating point numbers, assertions
-that two floating point numbers be equal will sometimes fail. To express
-that two numbers should be close to one another within a certain margin
-of error, use `beCloseTo`:
-
-```swift
-// Swift
-
-expect(actual).to(beCloseTo(expected, within: delta))
-```
-
-```objc
-// Objective-C
-
-expect(actual).to(beCloseTo(expected).within(delta));
-```
-
-For example, to assert that `10.01` is close to `10`, you can write:
-
-```swift
-// Swift
-
-expect(10.01).to(beCloseTo(10, within: 0.1))
-```
-
-```objc
-// Objective-C
-
-expect(@(10.01)).to(beCloseTo(@10).within(0.1));
-```
-
-There is also an operator shortcut available in Swift:
-
-```swift
-// Swift
-
-expect(actual) ≈ expected
-expect(actual) ≈ (expected, delta)
-
-```
-(Type option+x to get `≈` on a U.S. keyboard)
-
-The former version uses the default delta of 0.0001. Here is yet another way to do this:
-
-```swift
-// Swift
-
-expect(actual) ≈ expected ± delta
-expect(actual) == expected ± delta
-
-```
-(Type option+shift+= to get `±` on a U.S. keyboard)
-
-If you are comparing arrays of floating point numbers, you'll find the following useful:
-
-```swift
-// Swift
-
-expect([0.0, 2.0]) ≈ [0.0001, 2.0001]
-expect([0.0, 2.0]).to(beCloseTo([0.1, 2.1], within: 0.1))
-
-```
-
-> Values given to the `beCloseTo` matcher must be coercable into a
- `Double`.
-
-## Types/Classes
-
-```swift
-// Swift
-
-// Passes if 'instance' is an instance of 'aClass':
-expect(instance).to(beAnInstanceOf(aClass))
-
-// Passes if 'instance' is an instance of 'aClass' or any of its subclasses:
-expect(instance).to(beAKindOf(aClass))
-```
-
-```objc
-// Objective-C
-
-// Passes if 'instance' is an instance of 'aClass':
-expect(instance).to(beAnInstanceOf(aClass));
-
-// Passes if 'instance' is an instance of 'aClass' or any of its subclasses:
-expect(instance).to(beAKindOf(aClass));
-```
-
-> Instances must be Objective-C objects: subclasses of `NSObject`,
- or Swift objects bridged to Objective-C with the `@objc` prefix.
-
-For example, to assert that `dolphin` is a kind of `Mammal`:
-
-```swift
-// Swift
-
-expect(dolphin).to(beAKindOf(Mammal))
-```
-
-```objc
-// Objective-C
-
-expect(dolphin).to(beAKindOf([Mammal class]));
-```
-
-> `beAnInstanceOf` uses the `-[NSObject isMemberOfClass:]` method to
- test membership. `beAKindOf` uses `-[NSObject isKindOfClass:]`.
-
-## Truthiness
-
-```swift
-// Passes if 'actual' is not nil, true, or an object with a boolean value of true:
-expect(actual).to(beTruthy())
-
-// Passes if 'actual' is only true (not nil or an object conforming to Boolean true):
-expect(actual).to(beTrue())
-
-// Passes if 'actual' is nil, false, or an object with a boolean value of false:
-expect(actual).to(beFalsy())
-
-// Passes if 'actual' is only false (not nil or an object conforming to Boolean false):
-expect(actual).to(beFalse())
-
-// Passes if 'actual' is nil:
-expect(actual).to(beNil())
-```
-
-```objc
-// Objective-C
-
-// Passes if 'actual' is not nil, true, or an object with a boolean value of true:
-expect(actual).to(beTruthy());
-
-// Passes if 'actual' is only true (not nil or an object conforming to Boolean true):
-expect(actual).to(beTrue());
-
-// Passes if 'actual' is nil, false, or an object with a boolean value of false:
-expect(actual).to(beFalsy());
-
-// Passes if 'actual' is only false (not nil or an object conforming to Boolean false):
-expect(actual).to(beFalse());
-
-// Passes if 'actual' is nil:
-expect(actual).to(beNil());
-```
-
-## Swift Assertions
-
-If you're using Swift, you can use the `throwAssertion` matcher to check if an assertion is thrown (e.g. `fatalError()`). This is made possible by [@mattgallagher](https://github.com/mattgallagher)'s [CwlPreconditionTesting](https://github.com/mattgallagher/CwlPreconditionTesting) library.
-
-```swift
-// Swift
-
-// Passes if 'somethingThatThrows()' throws an assertion,
-// such as by calling 'fatalError()' or if a precondition fails:
-expect { try somethingThatThrows() }.to(throwAssertion())
-expect { () -> Void in fatalError() }.to(throwAssertion())
-expect { precondition(false) }.to(throwAssertion())
-
-// Passes if throwing an NSError is not equal to throwing an assertion:
-expect { throw NSError(domain: "test", code: 0, userInfo: nil) }.toNot(throwAssertion())
-
-// Passes if the code after the precondition check is not run:
-var reachedPoint1 = false
-var reachedPoint2 = false
-expect {
- reachedPoint1 = true
- precondition(false, "condition message")
- reachedPoint2 = true
-}.to(throwAssertion())
-
-expect(reachedPoint1) == true
-expect(reachedPoint2) == false
-```
-
-Notes:
-
-* This feature is only available in Swift.
-* It is only supported for `x86_64` binaries, meaning _you cannot run this matcher on iOS devices, only simulators_.
-* The tvOS simulator is supported, but using a different mechanism, requiring you to turn off the `Debug executable` scheme setting for your tvOS scheme's Test configuration.
-
-## Swift Error Handling
-
-You can use the `throwError` matcher to check if an error is thrown.
-
-```swift
-// Swift
-
-// Passes if 'somethingThatThrows()' throws an 'Error':
-expect { try somethingThatThrows() }.to(throwError())
-
-// Passes if 'somethingThatThrows()' throws an error within a particular domain:
-expect { try somethingThatThrows() }.to(throwError { (error: Error) in
- expect(error._domain).to(equal(NSCocoaErrorDomain))
-})
-
-// Passes if 'somethingThatThrows()' throws a particular error enum case:
-expect { try somethingThatThrows() }.to(throwError(NSCocoaError.PropertyListReadCorruptError))
-
-// Passes if 'somethingThatThrows()' throws an error of a particular type:
-expect { try somethingThatThrows() }.to(throwError(errorType: NimbleError.self))
-```
-
-When working directly with `Error` values, using the `matchError` matcher
-allows you to perform certain checks on the error itself without having to
-explicitly cast the error.
-
-The `matchError` matcher allows you to check whether or not the error:
-
-- is the same _type_ of error you are expecting.
-- represents a particular error value that you are expecting.
-
-This can be useful when using `Result` or `Promise` types, for example.
-
-```swift
-// Swift
-
-let actual: Error = ...
-
-// Passes if 'actual' represents any error value from the NimbleErrorEnum type:
-expect(actual).to(matchError(NimbleErrorEnum.self))
-
-// Passes if 'actual' represents the case 'timeout' from the NimbleErrorEnum type:
-expect(actual).to(matchError(NimbleErrorEnum.timeout))
-
-// Passes if 'actual' contains an NSError equal to the one provided:
-expect(actual).to(matchError(NSError(domain: "err", code: 123, userInfo: nil)))
-```
-
-Note: This feature is only available in Swift.
-
-## Exceptions
-
-```swift
-// Swift
-
-// Passes if 'actual', when evaluated, raises an exception:
-expect(actual).to(raiseException())
-
-// Passes if 'actual' raises an exception with the given name:
-expect(actual).to(raiseException(named: name))
-
-// Passes if 'actual' raises an exception with the given name and reason:
-expect(actual).to(raiseException(named: name, reason: reason))
-
-// Passes if 'actual' raises an exception which passes expectations defined in the given closure:
-// (in this case, if the exception's name begins with "a r")
-expect { exception.raise() }.to(raiseException { (exception: NSException) in
- expect(exception.name).to(beginWith("a r"))
-})
-```
-
-```objc
-// Objective-C
-
-// Passes if 'actual', when evaluated, raises an exception:
-expect(actual).to(raiseException())
-
-// Passes if 'actual' raises an exception with the given name
-expect(actual).to(raiseException().named(name))
-
-// Passes if 'actual' raises an exception with the given name and reason:
-expect(actual).to(raiseException().named(name).reason(reason))
-
-// Passes if 'actual' raises an exception and it passes expectations defined in the given block:
-// (in this case, if name begins with "a r")
-expect(actual).to(raiseException().satisfyingBlock(^(NSException *exception) {
- expect(exception.name).to(beginWith(@"a r"));
-}));
-```
-
-Note: Swift currently doesn't have exceptions (see [#220](https://github.com/Quick/Nimble/issues/220#issuecomment-172667064)).
-Only Objective-C code can raise exceptions that Nimble will catch.
-
-## Collection Membership
-
-```swift
-// Swift
-
-// Passes if all of the expected values are members of 'actual':
-expect(actual).to(contain(expected...))
-
-// Passes if 'actual' is empty (i.e. it contains no elements):
-expect(actual).to(beEmpty())
-```
-
-```objc
-// Objective-C
-
-// Passes if expected is a member of 'actual':
-expect(actual).to(contain(expected));
-
-// Passes if 'actual' is empty (i.e. it contains no elements):
-expect(actual).to(beEmpty());
-```
-
-> In Swift `contain` takes any number of arguments. The expectation
- passes if all of them are members of the collection. In Objective-C,
- `contain` only takes one argument [for now](https://github.com/Quick/Nimble/issues/27).
-
-For example, to assert that a list of sea creature names contains
-"dolphin" and "starfish":
-
-```swift
-// Swift
-
-expect(["whale", "dolphin", "starfish"]).to(contain("dolphin", "starfish"))
-```
-
-```objc
-// Objective-C
-
-expect(@[@"whale", @"dolphin", @"starfish"]).to(contain(@"dolphin"));
-expect(@[@"whale", @"dolphin", @"starfish"]).to(contain(@"starfish"));
-```
-
-> `contain` and `beEmpty` expect collections to be instances of
- `NSArray`, `NSSet`, or a Swift collection composed of `Equatable` elements.
-
-To test whether a set of elements is present at the beginning or end of
-an ordered collection, use `beginWith` and `endWith`:
-
-```swift
-// Swift
-
-// Passes if the elements in expected appear at the beginning of 'actual':
-expect(actual).to(beginWith(expected...))
-
-// Passes if the the elements in expected come at the end of 'actual':
-expect(actual).to(endWith(expected...))
-```
-
-```objc
-// Objective-C
-
-// Passes if the elements in expected appear at the beginning of 'actual':
-expect(actual).to(beginWith(expected));
-
-// Passes if the the elements in expected come at the end of 'actual':
-expect(actual).to(endWith(expected));
-```
-
-> `beginWith` and `endWith` expect collections to be instances of
- `NSArray`, or ordered Swift collections composed of `Equatable`
- elements.
-
- Like `contain`, in Objective-C `beginWith` and `endWith` only support
- a single argument [for now](https://github.com/Quick/Nimble/issues/27).
-
-For code that returns collections of complex objects without a strict
-ordering, there is the `containElementSatisfying` matcher:
-
-```swift
-// Swift
-
-struct Turtle {
- let color: String
-}
-
-let turtles: [Turtle] = functionThatReturnsSomeTurtlesInAnyOrder()
-
-// This set of matchers passes regardless of whether the array is
-// [{color: "blue"}, {color: "green"}] or [{color: "green"}, {color: "blue"}]:
-
-expect(turtles).to(containElementSatisfying({ turtle in
- return turtle.color == "green"
-}))
-expect(turtles).to(containElementSatisfying({ turtle in
- return turtle.color == "blue"
-}, "that is a turtle with color 'blue'"))
-
-// The second matcher will incorporate the provided string in the error message
-// should it fail
-```
-
-```objc
-// Objective-C
-
-@interface Turtle : NSObject
-@property (nonatomic, readonly, nonnull) NSString *color;
-@end
-
-@implementation Turtle
-@end
-
-NSArray * __nonnull turtles = functionThatReturnsSomeTurtlesInAnyOrder();
-
-// This set of matchers passes regardless of whether the array is
-// [{color: "blue"}, {color: "green"}] or [{color: "green"}, {color: "blue"}]:
-
-expect(turtles).to(containElementSatisfying(^BOOL(id __nonnull object) {
- return [[turtle color] isEqualToString:@"green"];
-}));
-expect(turtles).to(containElementSatisfying(^BOOL(id __nonnull object) {
- return [[turtle color] isEqualToString:@"blue"];
-}));
-```
-
-## Strings
-
-```swift
-// Swift
-
-// Passes if 'actual' contains 'substring':
-expect(actual).to(contain(substring))
-
-// Passes if 'actual' begins with 'prefix':
-expect(actual).to(beginWith(prefix))
-
-// Passes if 'actual' ends with 'suffix':
-expect(actual).to(endWith(suffix))
-
-// Passes if 'actual' represents the empty string, "":
-expect(actual).to(beEmpty())
-
-// Passes if 'actual' matches the regular expression defined in 'expected':
-expect(actual).to(match(expected))
-```
-
-```objc
-// Objective-C
-
-// Passes if 'actual' contains 'substring':
-expect(actual).to(contain(expected));
-
-// Passes if 'actual' begins with 'prefix':
-expect(actual).to(beginWith(prefix));
-
-// Passes if 'actual' ends with 'suffix':
-expect(actual).to(endWith(suffix));
-
-// Passes if 'actual' represents the empty string, "":
-expect(actual).to(beEmpty());
-
-// Passes if 'actual' matches the regular expression defined in 'expected':
-expect(actual).to(match(expected))
-```
-
-## Collection Elements
-
-Nimble provides a means to check that all elements of a collection pass a given expectation.
-
-### Swift
-
-In Swift, the collection must be an instance of a type conforming to
-`Sequence`.
-
-```swift
-// Swift
-
-// Providing a custom function:
-expect([1, 2, 3, 4]).to(allPass { $0! < 5 })
-
-// Composing the expectation with another matcher:
-expect([1, 2, 3, 4]).to(allPass(beLessThan(5)))
-```
-
-### Objective-C
-
-In Objective-C, the collection must be an instance of a type which implements
-the `NSFastEnumeration` protocol, and whose elements are instances of a type
-which subclasses `NSObject`.
-
-Additionally, unlike in Swift, there is no override to specify a custom
-matcher function.
-
-```objc
-// Objective-C
-
-expect(@[@1, @2, @3, @4]).to(allPass(beLessThan(@5)));
-```
-
-## Collection Count
-
-```swift
-// Swift
-
-// Passes if 'actual' contains the 'expected' number of elements:
-expect(actual).to(haveCount(expected))
-
-// Passes if 'actual' does _not_ contain the 'expected' number of elements:
-expect(actual).notTo(haveCount(expected))
-```
-
-```objc
-// Objective-C
-
-// Passes if 'actual' contains the 'expected' number of elements:
-expect(actual).to(haveCount(expected))
-
-// Passes if 'actual' does _not_ contain the 'expected' number of elements:
-expect(actual).notTo(haveCount(expected))
-```
-
-For Swift, the actual value must be an instance of a type conforming to `Collection`.
-For example, instances of `Array`, `Dictionary`, or `Set`.
-
-For Objective-C, the actual value must be one of the following classes, or their subclasses:
-
- - `NSArray`,
- - `NSDictionary`,
- - `NSSet`, or
- - `NSHashTable`.
-
-## Notifications
-
-```swift
-// Swift
-let testNotification = Notification(name: "Foo", object: nil)
-
-// passes if the closure in expect { ... } posts a notification to the default
-// notification center.
-expect {
- NotificationCenter.default.postNotification(testNotification)
-}.to(postNotifications(equal([testNotification]))
-
-// passes if the closure in expect { ... } posts a notification to a given
-// notification center
-let notificationCenter = NotificationCenter()
-expect {
- notificationCenter.postNotification(testNotification)
-}.to(postNotifications(equal([testNotification]), fromNotificationCenter: notificationCenter))
-```
-
-> This matcher is only available in Swift.
-
-## Matching a value to any of a group of matchers
-
-```swift
-// Swift
-
-// passes if actual is either less than 10 or greater than 20
-expect(actual).to(satisfyAnyOf(beLessThan(10), beGreaterThan(20)))
-
-// can include any number of matchers -- the following will pass
-// **be careful** -- too many matchers can be the sign of an unfocused test
-expect(6).to(satisfyAnyOf(equal(2), equal(3), equal(4), equal(5), equal(6), equal(7)))
-
-// in Swift you also have the option to use the || operator to achieve a similar function
-expect(82).to(beLessThan(50) || beGreaterThan(80))
-```
-
-```objc
-// Objective-C
-
-// passes if actual is either less than 10 or greater than 20
-expect(actual).to(satisfyAnyOf(beLessThan(@10), beGreaterThan(@20)))
-
-// can include any number of matchers -- the following will pass
-// **be careful** -- too many matchers can be the sign of an unfocused test
-expect(@6).to(satisfyAnyOf(equal(@2), equal(@3), equal(@4), equal(@5), equal(@6), equal(@7)))
-```
-
-Note: This matcher allows you to chain any number of matchers together. This provides flexibility,
- but if you find yourself chaining many matchers together in one test, consider whether you
- could instead refactor that single test into multiple, more precisely focused tests for
- better coverage.
-
-## Custom Validation
-
-```swift
-// Swift
-
-// passes if .succeeded is returned from the closure
-expect({
- guard case .enumCaseWithAssociatedValueThatIDontCareAbout = actual else {
- return .failed(reason: "wrong enum case")
- }
-
- return .succeeded
-}).to(succeed())
-
-// passes if .failed is returned from the closure
-expect({
- guard case .enumCaseWithAssociatedValueThatIDontCareAbout = actual else {
- return .failed(reason: "wrong enum case")
- }
-
- return .succeeded
-}).notTo(succeed())
-```
-
-The `String` provided with `.failed()` is shown when the test fails.
-
-When using `toEventually()` be careful not to make state changes or run process intensive code since this closure will be ran many times.
-
-# Writing Your Own Matchers
-
-In Nimble, matchers are Swift functions that take an expected
-value and return a `Predicate` closure. Take `equal`, for example:
-
-```swift
-// Swift
-
-public func equal(expectedValue: T?) -> Predicate {
- // Can be shortened to:
- // Predicate { actual in ... }
- //
- // But shown with types here for clarity.
- return Predicate { (actualExpression: Expression) throws -> PredicateResult in
- let msg = ExpectationMessage.expectedActualValueTo("equal <\(expectedValue)>")
- if let actualValue = try actualExpression.evaluate() {
- return PredicateResult(
- bool: actualValue == expectedValue!,
- message: msg
- )
- } else {
- return PredicateResult(
- status: .fail,
- message: msg.appendedBeNilHint()
- )
- }
- }
-}
-```
-
-The return value of a `Predicate` closure is a `PredicateResult` that indicates
-whether the actual value matches the expectation and what error message to
-display on failure.
-
-> The actual `equal` matcher function does not match when
- `expected` are nil; the example above has been edited for brevity.
-
-Since matchers are just Swift functions, you can define them anywhere:
-at the top of your test file, in a file shared by all of your tests, or
-in an Xcode project you distribute to others.
-
-> If you write a matcher you think everyone can use, consider adding it
- to Nimble's built-in set of matchers by sending a pull request! Or
- distribute it yourself via GitHub.
-
-For examples of how to write your own matchers, just check out the
-[`Matchers` directory](https://github.com/Quick/Nimble/tree/master/Sources/Nimble/Matchers)
-to see how Nimble's built-in set of matchers are implemented. You can
-also check out the tips below.
-
-## PredicateResult
-
-`PredicateResult` is the return struct that `Predicate` return to indicate
-success and failure. A `PredicateResult` is made up of two values:
-`PredicateStatus` and `ExpectationMessage`.
-
-Instead of a boolean, `PredicateStatus` captures a trinary set of values:
-
-```swift
-// Swift
-
-public enum PredicateStatus {
-// The predicate "passes" with the given expression
-// eg - expect(1).to(equal(1))
-case matches
-
-// The predicate "fails" with the given expression
-// eg - expect(1).toNot(equal(1))
-case doesNotMatch
-
-// The predicate never "passes" with the given expression, even if negated
-// eg - expect(nil as Int?).toNot(equal(1))
-case fail
-
-// ...
-}
-```
-
-Meanwhile, `ExpectationMessage` provides messaging semantics for error reporting.
-
-```swift
-// Swift
-
-public indirect enum ExpectationMessage {
-// Emits standard error message:
-// eg - "expected to , got "
-case expectedActualValueTo(/* message: */ String)
-
-// Allows any free-form message
-// eg - ""
-case fail(/* message: */ String)
-
-// ...
-}
-```
-
-Predicates should usually depend on either `.expectedActualValueTo(..)` or
-`.fail(..)` when reporting errors. Special cases can be used for the other enum
-cases.
-
-Finally, if your Predicate utilizes other Predicates, you can utilize
-`.appended(details:)` and `.appended(message:)` methods to annotate an existing
-error with more details.
-
-A common message to append is failing on nils. For that, `.appendedBeNilHint()`
-can be used.
-
-## Lazy Evaluation
-
-`actualExpression` is a lazy, memoized closure around the value provided to the
-`expect` function. The expression can either be a closure or a value directly
-passed to `expect(...)`. In order to determine whether that value matches,
-custom matchers should call `actualExpression.evaluate()`:
-
-```swift
-// Swift
-
-public func beNil() -> Predicate {
- // Predicate.simpleNilable(..) automatically generates ExpectationMessage for
- // us based on the string we provide to it. Also, the 'Nilable' postfix indicates
- // that this Predicate supports matching against nil actualExpressions, instead of
- // always resulting in a PredicateStatus.fail result -- which is true for
- // Predicate.simple(..)
- return Predicate.simpleNilable("be nil") { actualExpression in
- let actualValue = try actualExpression.evaluate()
- return PredicateStatus(bool: actualValue == nil)
- }
-}
-```
-
-In the above example, `actualExpression` is not `nil` -- it is a closure
-that returns a value. The value it returns, which is accessed via the
-`evaluate()` method, may be `nil`. If that value is `nil`, the `beNil`
-matcher function returns `true`, indicating that the expectation passed.
-
-## Type Checking via Swift Generics
-
-Using Swift's generics, matchers can constrain the type of the actual value
-passed to the `expect` function by modifying the return type.
-
-For example, the following matcher, `haveDescription`, only accepts actual
-values that implement the `Printable` protocol. It checks their `description`
-against the one provided to the matcher function, and passes if they are the same:
-
-```swift
-// Swift
-
-public func haveDescription(description: String) -> Predicate {
- return Predicate.simple("have description") { actual in
- return PredicateStatus(bool: actual.evaluate().description == description)
- }
-}
-```
-
-## Customizing Failure Messages
-
-When using `Predicate.simple(..)` or `Predicate.simpleNilable(..)`, Nimble
-outputs the following failure message when an expectation fails:
-
-```swift
-// where `message` is the first string argument and
-// `actual` is the actual value received in `expect(..)`
-"expected to \(message), got <\(actual)>"
-```
-
-You can customize this message by modifying the way you create a `Predicate`.
-
-### Basic Customization
-
-For slightly more complex error messaging, receive the created failure message
-with `Predicate.define(..)`:
-
-```swift
-// Swift
-
-public func equal(_ expectedValue: T?) -> Predicate {
- return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in
- let actualValue = try actualExpression.evaluate()
- let matches = actualValue == expectedValue && expectedValue != nil
- if expectedValue == nil || actualValue == nil {
- if expectedValue == nil && actualValue != nil {
- return PredicateResult(
- status: .fail,
- message: msg.appendedBeNilHint()
- )
- }
- return PredicateResult(status: .fail, message: msg)
- }
- return PredicateResult(bool: matches, message: msg)
- }
-}
-```
-
-In the example above, `msg` is defined based on the string given to
-`Predicate.define`. The code looks akin to:
-
-```swift
-// Swift
-
-let msg = ExpectationMessage.expectedActualValueTo("equal <\(stringify(expectedValue))>")
-```
-
-### Full Customization
-
-To fully customize the behavior of the Predicate, use the overload that expects
-a `PredicateResult` to be returned.
-
-Along with `PredicateResult`, there are other `ExpectationMessage` enum values you can use:
-
-```swift
-public indirect enum ExpectationMessage {
-// Emits standard error message:
-// eg - "expected to , got "
-case expectedActualValueTo(/* message: */ String)
-
-// Allows any free-form message
-// eg - ""
-case fail(/* message: */ String)
-
-// Emits standard error message with a custom actual value instead of the default.
-// eg - "expected to , got "
-case expectedCustomValueTo(/* message: */ String, /* actual: */ String)
-
-// Emits standard error message without mentioning the actual value
-// eg - "expected to "
-case expectedTo(/* message: */ String)
-
-// ...
-}
-```
-
-For matchers that compose other matchers, there are a handful of helper
-functions to annotate messages.
-
-`appended(message: String)` is used to append to the original failure message:
-
-```swift
-// produces "expected to be true, got (use beFalse() for inverse)"
-// appended message do show up inline in Xcode.
-.expectedActualValueTo("be true").appended(message: " (use beFalse() for inverse)")
-```
-
-For a more comprehensive message that spans multiple lines, use
-`appended(details: String)` instead:
-
-```swift
-// produces "expected to be true, got \n\nuse beFalse() for inverse\nor use beNil()"
-// details do not show inline in Xcode, but do show up in test logs.
-.expectedActualValueTo("be true").appended(details: "use beFalse() for inverse\nor use beNil()")
-```
-
-## Supporting Objective-C
-
-To use a custom matcher written in Swift from Objective-C, you'll have
-to extend the `NMBObjCMatcher` class, adding a new class method for your
-custom matcher. The example below defines the class method
-`+[NMBObjCMatcher beNilMatcher]`:
-
-```swift
-// Swift
-
-extension NMBObjCMatcher {
- public class func beNilMatcher() -> NMBObjCMatcher {
- return NMBObjCMatcher { actualBlock, failureMessage, location in
- let block = ({ actualBlock() as NSObject? })
- let expr = Expression(expression: block, location: location)
- return beNil().matches(expr, failureMessage: failureMessage)
- }
- }
-}
-```
-
-The above allows you to use the matcher from Objective-C:
-
-```objc
-// Objective-C
-
-expect(actual).to([NMBObjCMatcher beNilMatcher]());
-```
-
-To make the syntax easier to use, define a C function that calls the
-class method:
-
-```objc
-// Objective-C
-
-FOUNDATION_EXPORT id beNil() {
- return [NMBObjCMatcher beNilMatcher];
-}
-```
-
-### Properly Handling `nil` in Objective-C Matchers
-
-When supporting Objective-C, make sure you handle `nil` appropriately.
-Like [Cedar](https://github.com/pivotal/cedar/issues/100),
-**most matchers do not match with nil**. This is to bring prevent test
-writers from being surprised by `nil` values where they did not expect
-them.
-
-Nimble provides the `beNil` matcher function for test writer that want
-to make expectations on `nil` objects:
-
-```objc
-// Objective-C
-
-expect(nil).to(equal(nil)); // fails
-expect(nil).to(beNil()); // passes
-```
-
-If your matcher does not want to match with nil, you use `NonNilMatcherFunc`
-and the `canMatchNil` constructor on `NMBObjCMatcher`. Using both types will
-automatically generate expected value failure messages when they're nil.
-
-```swift
-
-public func beginWith(startingElement: T) -> NonNilMatcherFunc {
- return NonNilMatcherFunc { actualExpression, failureMessage in
- failureMessage.postfixMessage = "begin with <\(startingElement)>"
- if let actualValue = actualExpression.evaluate() {
- var actualGenerator = actualValue.makeIterator()
- return actualGenerator.next() == startingElement
- }
- return false
- }
-}
-
-extension NMBObjCMatcher {
- public class func beginWithMatcher(expected: AnyObject) -> NMBObjCMatcher {
- return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in
- let actual = actualExpression.evaluate()
- let expr = actualExpression.cast { $0 as? NMBOrderedCollection }
- return beginWith(expected).matches(expr, failureMessage: failureMessage)
- }
- }
-}
-```
-
-## Migrating from the Old Matcher API
-
-Previously (`<7.0.0`), Nimble supported matchers via the following types:
-
-- `Matcher`
-- `NonNilMatcherFunc`
-- `MatcherFunc`
-
-All of those types have been replaced by `Predicate`. While migrating can be a
-lot of work, Nimble currently provides several steps to aid migration of your
-custom matchers:
-
-### Minimal Step - Use `.predicate`
-
-Nimble provides an extension to the old types that automatically naively
-converts those types to the newer `Predicate`.
-
-```swift
-// Swift
-public func beginWith(startingElement: T) -> Predicate {
- return NonNilMatcherFunc { actualExpression, failureMessage in
- failureMessage.postfixMessage = "begin with <\(startingElement)>"
- if let actualValue = actualExpression.evaluate() {
- var actualGenerator = actualValue.makeIterator()
- return actualGenerator.next() == startingElement
- }
- return false
- }.predicate
-}
-```
-
-This is the simpliest way to externally support `Predicate` which allows easier
-composition than the old Nimble matcher interface, with minimal effort to change.
-
-### Convert to use `Predicate` Type with Old Matcher Constructor
-
-The second most convenient step is to utilize special constructors that
-`Predicate` supports that closely align to the constructors of the old Nimble
-matcher types.
-
-```swift
-// Swift
-public func beginWith(startingElement: T) -> Predicate {
- return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in
- failureMessage.postfixMessage = "begin with <\(startingElement)>"
- if let actualValue = actualExpression.evaluate() {
- var actualGenerator = actualValue.makeIterator()
- return actualGenerator.next() == startingElement
- }
- return false
- }
-}
-```
-
-This allows you to completely drop the old types from your code, although the
-intended behavior may alter slightly to what is desired.
-
-### Convert to `Predicate` Type with Preferred Constructor
-
-Finally, you can convert to the native `Predicate` format using one of the
-constructors not used to assist in the migration.
-
-### Deprecation Roadmap
-
-Nimble 7 introduces `Predicate` but will support the old types with warning
-deprecations. A couple major releases of Nimble will remain backwards
-compatible with the old matcher api, although new features may not be
-backported.
-
-The deprecating plan is a 3 major versions removal. Which is as follows:
-
- 1. Introduce new `Predicate` API, deprecation warning for old matcher APIs.
- (Nimble `v7.x.x` and `v8.x.x`)
- 2. Introduce warnings on migration-path features (`.predicate`,
- `Predicate`-constructors with similar arguments to old API). (Nimble
- `v9.x.x`)
- 3. Remove old API. (Nimble `v10.x.x`)
-
-
-# Installing Nimble
-
-> Nimble can be used on its own, or in conjunction with its sister
- project, [Quick](https://github.com/Quick/Quick). To install both
- Quick and Nimble, follow [the installation instructions in the Quick
- Documentation](https://github.com/Quick/Quick/blob/master/Documentation/en-us/InstallingQuick.md).
-
-Nimble can currently be installed in one of two ways: using CocoaPods, or with
-git submodules.
-
-## Installing Nimble as a Submodule
-
-To use Nimble as a submodule to test your macOS, iOS or tvOS applications, follow
-these 4 easy steps:
-
-1. Clone the Nimble repository
-2. Add Nimble.xcodeproj to the Xcode workspace for your project
-3. Link Nimble.framework to your test target
-4. Start writing expectations!
-
-For more detailed instructions on each of these steps,
-read [How to Install Quick](https://github.com/Quick/Quick#how-to-install-quick).
-Ignore the steps involving adding Quick to your project in order to
-install just Nimble.
-
-## Installing Nimble via CocoaPods
-
-To use Nimble in CocoaPods to test your macOS, iOS or tvOS applications, add
-Nimble to your podfile and add the ```use_frameworks!``` line to enable Swift
-support for CocoaPods.
-
-```ruby
-platform :ios, '8.0'
-
-source 'https://github.com/CocoaPods/Specs.git'
-
-# Whatever pods you need for your app go here
-
-target 'YOUR_APP_NAME_HERE_Tests', :exclusive => true do
- use_frameworks!
- pod 'Nimble', '~> 6.0.0'
-end
-```
-
-Finally run `pod install`.
-
-## Installing Nimble via Accio
-
-Add the following to your Package.swift:
-
-```swift
-.package(url: "https://github.com/Quick/Nimble.git", .upToNextMajor(from: "8.0.1")),
-```
-
-Next, add `Nimble` to your App targets dependencies like so:
-
-```swift
-.testTarget(
- name: "AppTests",
- dependencies: [
- "Nimble",
- ]
-),
-```
-
-Then run `accio update`.
-
-## Using Nimble without XCTest
-
-Nimble is integrated with XCTest to allow it work well when used in Xcode test
-bundles, however it can also be used in a standalone app. After installing
-Nimble using one of the above methods, there are two additional steps required
-to make this work.
-
-1. Create a custom assertion handler and assign an instance of it to the
- global `NimbleAssertionHandler` variable. For example:
-
-```swift
-class MyAssertionHandler : AssertionHandler {
- func assert(assertion: Bool, message: FailureMessage, location: SourceLocation) {
- if (!assertion) {
- print("Expectation failed: \(message.stringValue)")
- }
- }
-}
-```
-```swift
-// Somewhere before you use any assertions
-NimbleAssertionHandler = MyAssertionHandler()
-```
-
-2. Add a post-build action to fix an issue with the Swift XCTest support
- library being unnecessarily copied into your app
- * Edit your scheme in Xcode, and navigate to Build -> Post-actions
- * Click the "+" icon and select "New Run Script Action"
- * Open the "Provide build settings from" dropdown and select your target
- * Enter the following script contents:
-```
-rm "${SWIFT_STDLIB_TOOL_DESTINATION_DIR}/libswiftXCTest.dylib"
-```
-
-You can now use Nimble assertions in your code and handle failures as you see
-fit.
diff --git a/Pods/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift b/Pods/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift
deleted file mode 100644
index abaf532..0000000
--- a/Pods/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift
+++ /dev/null
@@ -1,18 +0,0 @@
-import Foundation
-
-/// Protocol for the assertion handler that Nimble uses for all expectations.
-public protocol AssertionHandler {
- func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation)
-}
-
-/// Global backing interface for assertions that Nimble creates.
-/// Defaults to a private test handler that passes through to XCTest.
-///
-/// If XCTest is not available, you must assign your own assertion handler
-/// before using any matchers, otherwise Nimble will abort the program.
-///
-/// @see AssertionHandler
-public var NimbleAssertionHandler: AssertionHandler = { () -> AssertionHandler in
- // swiftlint:disable:previous identifier_name
- return isXCTestAvailable() ? NimbleXCTestHandler() : NimbleXCTestUnavailableHandler()
-}()
diff --git a/Pods/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift b/Pods/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift
deleted file mode 100644
index 94a9030..0000000
--- a/Pods/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-/// AssertionDispatcher allows multiple AssertionHandlers to receive
-/// assertion messages.
-///
-/// @warning Does not fully dispatch if one of the handlers raises an exception.
-/// This is possible with XCTest-based assertion handlers.
-///
-public class AssertionDispatcher: AssertionHandler {
- let handlers: [AssertionHandler]
-
- public init(handlers: [AssertionHandler]) {
- self.handlers = handlers
- }
-
- public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) {
- for handler in handlers {
- handler.assert(assertion, message: message, location: location)
- }
- }
-}
diff --git a/Pods/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift b/Pods/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift
deleted file mode 100644
index 0f5df59..0000000
--- a/Pods/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift
+++ /dev/null
@@ -1,127 +0,0 @@
-import Foundation
-
-/// A data structure that stores information about an assertion when
-/// AssertionRecorder is set as the Nimble assertion handler.
-///
-/// @see AssertionRecorder
-/// @see AssertionHandler
-public struct AssertionRecord: CustomStringConvertible {
- /// Whether the assertion succeeded or failed
- public let success: Bool
- /// The failure message the assertion would display on failure.
- public let message: FailureMessage
- /// The source location the expectation occurred on.
- public let location: SourceLocation
-
- public var description: String {
- return "AssertionRecord { success=\(success), message='\(message.stringValue)', location=\(location) }"
- }
-}
-
-/// An AssertionHandler that silently records assertions that Nimble makes.
-/// This is useful for testing failure messages for matchers.
-///
-/// @see AssertionHandler
-public class AssertionRecorder: AssertionHandler {
- /// All the assertions that were captured by this recorder
- public var assertions = [AssertionRecord]()
-
- public init() {}
-
- public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) {
- assertions.append(
- AssertionRecord(
- success: assertion,
- message: message,
- location: location))
- }
-}
-
-extension NMBExceptionCapture {
- internal func tryBlockThrows(_ unsafeBlock: () throws -> Void) throws {
- var catchedError: Error?
- tryBlock {
- do {
- try unsafeBlock()
- } catch {
- catchedError = error
- }
- }
- if let error = catchedError {
- throw error
- }
- }
-}
-
-/// Allows you to temporarily replace the current Nimble assertion handler with
-/// the one provided for the scope of the closure.
-///
-/// Once the closure finishes, then the original Nimble assertion handler is restored.
-///
-/// @see AssertionHandler
-public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler,
- file: FileString = #file,
- line: UInt = #line,
- closure: () throws -> Void) {
- let environment = NimbleEnvironment.activeInstance
- let oldRecorder = environment.assertionHandler
- let capturer = NMBExceptionCapture(handler: nil, finally: ({
- environment.assertionHandler = oldRecorder
- }))
- environment.assertionHandler = tempAssertionHandler
-
- do {
- try capturer.tryBlockThrows {
- try closure()
- }
- } catch {
- let failureMessage = FailureMessage()
- failureMessage.stringValue = "unexpected error thrown: <\(error)>"
- let location = SourceLocation(file: file, line: line)
- tempAssertionHandler.assert(false, message: failureMessage, location: location)
- }
-}
-
-/// Captures expectations that occur in the given closure. Note that all
-/// expectations will still go through to the default Nimble handler.
-///
-/// This can be useful if you want to gather information about expectations
-/// that occur within a closure.
-///
-/// @param silently expectations are no longer send to the default Nimble
-/// assertion handler when this is true. Defaults to false.
-///
-/// @see gatherFailingExpectations
-public func gatherExpectations(silently: Bool = false, closure: () -> Void) -> [AssertionRecord] {
- let previousRecorder = NimbleEnvironment.activeInstance.assertionHandler
- let recorder = AssertionRecorder()
- let handlers: [AssertionHandler]
-
- if silently {
- handlers = [recorder]
- } else {
- handlers = [recorder, previousRecorder]
- }
-
- let dispatcher = AssertionDispatcher(handlers: handlers)
- withAssertionHandler(dispatcher, closure: closure)
- return recorder.assertions
-}
-
-/// Captures failed expectations that occur in the given closure. Note that all
-/// expectations will still go through to the default Nimble handler.
-///
-/// This can be useful if you want to gather information about failed
-/// expectations that occur within a closure.
-///
-/// @param silently expectations are no longer send to the default Nimble
-/// assertion handler when this is true. Defaults to false.
-///
-/// @see gatherExpectations
-/// @see raiseException source for an example use case.
-public func gatherFailingExpectations(silently: Bool = false, closure: () -> Void) -> [AssertionRecord] {
- let assertions = gatherExpectations(silently: silently, closure: closure)
- return assertions.filter { assertion in
- !assertion.success
- }
-}
diff --git a/Pods/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift b/Pods/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift
deleted file mode 100644
index 5338a46..0000000
--- a/Pods/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift
+++ /dev/null
@@ -1,191 +0,0 @@
-import Foundation
-
-#if canImport(Darwin) && !SWIFT_PACKAGE
-
-private func from(objcPredicate: NMBPredicate) -> Predicate {
- return Predicate { actualExpression in
- let result = objcPredicate.satisfies(({ try actualExpression.evaluate() }),
- location: actualExpression.location)
- return result.toSwift()
- }
-}
-
-internal struct ObjCMatcherWrapper: Matcher {
- let matcher: NMBMatcher
-
- func matches(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool {
- return matcher.matches(
- // swiftlint:disable:next force_try
- ({ try! actualExpression.evaluate() }),
- failureMessage: failureMessage,
- location: actualExpression.location)
- }
-
- func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool {
- return matcher.doesNotMatch(
- // swiftlint:disable:next force_try
- ({ try! actualExpression.evaluate() }),
- failureMessage: failureMessage,
- location: actualExpression.location)
- }
-}
-
-// Equivalent to Expectation, but for Nimble's Objective-C interface
-public class NMBExpectation: NSObject {
- // swiftlint:disable identifier_name
- internal let _actualBlock: () -> NSObject?
- internal var _negative: Bool
- internal let _file: FileString
- internal let _line: UInt
- internal var _timeout: TimeInterval = 1.0
- // swiftlint:enable identifier_name
-
- @objc public init(actualBlock: @escaping () -> NSObject?, negative: Bool, file: FileString, line: UInt) {
- self._actualBlock = actualBlock
- self._negative = negative
- self._file = file
- self._line = line
- }
-
- private var expectValue: Expectation {
- return expect(_file, line: _line) {
- self._actualBlock() as NSObject?
- }
- }
-
- @objc public var withTimeout: (TimeInterval) -> NMBExpectation {
- return { timeout in self._timeout = timeout
- return self
- }
- }
-
- @objc public var to: (NMBMatcher) -> Void {
- return { matcher in
- if let pred = matcher as? NMBPredicate {
- self.expectValue.to(from(objcPredicate: pred))
- } else {
- self.expectValue.to(ObjCMatcherWrapper(matcher: matcher))
- }
- }
- }
-
- @objc public var toWithDescription: (NMBMatcher, String) -> Void {
- return { matcher, description in
- if let pred = matcher as? NMBPredicate {
- self.expectValue.to(from(objcPredicate: pred), description: description)
- } else {
- self.expectValue.to(ObjCMatcherWrapper(matcher: matcher), description: description)
- }
- }
- }
-
- @objc public var toNot: (NMBMatcher) -> Void {
- return { matcher in
- if let pred = matcher as? NMBPredicate {
- self.expectValue.toNot(from(objcPredicate: pred))
- } else {
- self.expectValue.toNot(ObjCMatcherWrapper(matcher: matcher))
- }
- }
- }
-
- @objc public var toNotWithDescription: (NMBMatcher, String) -> Void {
- return { matcher, description in
- if let pred = matcher as? NMBPredicate {
- self.expectValue.toNot(from(objcPredicate: pred), description: description)
- } else {
- self.expectValue.toNot(ObjCMatcherWrapper(matcher: matcher), description: description)
- }
- }
- }
-
- @objc public var notTo: (NMBMatcher) -> Void { return toNot }
-
- @objc public var notToWithDescription: (NMBMatcher, String) -> Void { return toNotWithDescription }
-
- @objc public var toEventually: (NMBMatcher) -> Void {
- return { matcher in
- if let pred = matcher as? NMBPredicate {
- self.expectValue.toEventually(
- from(objcPredicate: pred),
- timeout: self._timeout,
- description: nil
- )
- } else {
- self.expectValue.toEventually(
- ObjCMatcherWrapper(matcher: matcher),
- timeout: self._timeout,
- description: nil
- )
- }
- }
- }
-
- @objc public var toEventuallyWithDescription: (NMBMatcher, String) -> Void {
- return { matcher, description in
- if let pred = matcher as? NMBPredicate {
- self.expectValue.toEventually(
- from(objcPredicate: pred),
- timeout: self._timeout,
- description: description
- )
- } else {
- self.expectValue.toEventually(
- ObjCMatcherWrapper(matcher: matcher),
- timeout: self._timeout,
- description: description
- )
- }
- }
- }
-
- @objc public var toEventuallyNot: (NMBMatcher) -> Void {
- return { matcher in
- if let pred = matcher as? NMBPredicate {
- self.expectValue.toEventuallyNot(
- from(objcPredicate: pred),
- timeout: self._timeout,
- description: nil
- )
- } else {
- self.expectValue.toEventuallyNot(
- ObjCMatcherWrapper(matcher: matcher),
- timeout: self._timeout,
- description: nil
- )
- }
- }
- }
-
- @objc public var toEventuallyNotWithDescription: (NMBMatcher, String) -> Void {
- return { matcher, description in
- if let pred = matcher as? NMBPredicate {
- self.expectValue.toEventuallyNot(
- from(objcPredicate: pred),
- timeout: self._timeout,
- description: description
- )
- } else {
- self.expectValue.toEventuallyNot(
- ObjCMatcherWrapper(matcher: matcher),
- timeout: self._timeout,
- description: description
- )
- }
- }
- }
-
- @objc public var toNotEventually: (NMBMatcher) -> Void {
- return toEventuallyNot
- }
-
- @objc public var toNotEventuallyWithDescription: (NMBMatcher, String) -> Void {
- return toEventuallyNotWithDescription
- }
-
- @objc public class func failWithMessage(_ message: String, file: FileString, line: UInt) {
- fail(message, location: SourceLocation(file: file, line: line))
- }
-}
-
-#endif
diff --git a/Pods/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift b/Pods/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift
deleted file mode 100644
index a91efe3..0000000
--- a/Pods/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift
+++ /dev/null
@@ -1,95 +0,0 @@
-import Foundation
-
-#if canImport(Darwin)
-
-// swiftlint:disable line_length
-public typealias MatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage) throws -> Bool
-public typealias FullMatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) throws -> Bool
-// swiftlint:enable line_length
-
-public class NMBObjCMatcher: NSObject, NMBMatcher {
- // swiftlint:disable identifier_name
- let _match: MatcherBlock
- let _doesNotMatch: MatcherBlock
- // swiftlint:enable identifier_name
- let canMatchNil: Bool
-
- public init(canMatchNil: Bool, matcher: @escaping MatcherBlock, notMatcher: @escaping MatcherBlock) {
- self.canMatchNil = canMatchNil
- self._match = matcher
- self._doesNotMatch = notMatcher
- }
-
- public convenience init(matcher: @escaping MatcherBlock) {
- self.init(canMatchNil: true, matcher: matcher)
- }
-
- public convenience init(canMatchNil: Bool, matcher: @escaping MatcherBlock) {
- self.init(canMatchNil: canMatchNil, matcher: matcher, notMatcher: ({ actualExpression, failureMessage in
- return try !matcher(actualExpression, failureMessage)
- }))
- }
-
- public convenience init(matcher: @escaping FullMatcherBlock) {
- self.init(canMatchNil: true, matcher: matcher)
- }
-
- public convenience init(canMatchNil: Bool, matcher: @escaping FullMatcherBlock) {
- self.init(canMatchNil: canMatchNil, matcher: ({ actualExpression, failureMessage in
- return try matcher(actualExpression, failureMessage, false)
- }), notMatcher: ({ actualExpression, failureMessage in
- return try matcher(actualExpression, failureMessage, true)
- }))
- }
-
- private func canMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool {
- do {
- if !canMatchNil {
- if try actualExpression.evaluate() == nil {
- failureMessage.postfixActual = " (use beNil() to match nils)"
- return false
- }
- }
- } catch let error {
- failureMessage.actualValue = "an unexpected error thrown: \(error)"
- return false
- }
- return true
- }
-
- public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
- let expr = Expression(expression: actualBlock, location: location)
- let result: Bool
- do {
- result = try _match(expr, failureMessage)
- } catch let error {
- failureMessage.stringValue = "unexpected error thrown: <\(error)>"
- return false
- }
-
- if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) {
- return result
- } else {
- return false
- }
- }
-
- public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
- let expr = Expression(expression: actualBlock, location: location)
- let result: Bool
- do {
- result = try _doesNotMatch(expr, failureMessage)
- } catch let error {
- failureMessage.stringValue = "unexpected error thrown: <\(error)>"
- return false
- }
-
- if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) {
- return result
- } else {
- return false
- }
- }
-}
-
-#endif
diff --git a/Pods/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift b/Pods/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift
deleted file mode 100644
index 1b2e8c0..0000000
--- a/Pods/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift
+++ /dev/null
@@ -1,43 +0,0 @@
-import Dispatch
-import Foundation
-
-/// "Global" state of Nimble is stored here. Only DSL functions should access / be aware of this
-/// class' existence
-internal class NimbleEnvironment: NSObject {
- static var activeInstance: NimbleEnvironment {
- get {
- let env = Thread.current.threadDictionary["NimbleEnvironment"]
- if let env = env as? NimbleEnvironment {
- return env
- } else {
- let newEnv = NimbleEnvironment()
- self.activeInstance = newEnv
- return newEnv
- }
- }
- set {
- Thread.current.threadDictionary["NimbleEnvironment"] = newValue
- }
- }
-
- // swiftlint:disable:next todo
- // TODO: eventually migrate the global to this environment value
- var assertionHandler: AssertionHandler {
- get { return NimbleAssertionHandler }
- set { NimbleAssertionHandler = newValue }
- }
-
- var suppressTVOSAssertionWarning: Bool = false
- var awaiter: Awaiter
-
- override init() {
- let timeoutQueue = DispatchQueue.global(qos: .userInitiated)
- awaiter = Awaiter(
- waitLock: AssertionWaitLock(),
- asyncQueue: .main,
- timeoutQueue: timeoutQueue
- )
-
- super.init()
- }
-}
diff --git a/Pods/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift b/Pods/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift
deleted file mode 100644
index 719bf44..0000000
--- a/Pods/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift
+++ /dev/null
@@ -1,91 +0,0 @@
-import Foundation
-import XCTest
-
-/// Default handler for Nimble. This assertion handler passes failures along to
-/// XCTest.
-public class NimbleXCTestHandler: AssertionHandler {
- public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) {
- if !assertion {
- recordFailure("\(message.stringValue)\n", location: location)
- }
- }
-}
-
-/// Alternative handler for Nimble. This assertion handler passes failures along
-/// to XCTest by attempting to reduce the failure message size.
-public class NimbleShortXCTestHandler: AssertionHandler {
- public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) {
- if !assertion {
- let msg: String
- if let actual = message.actualValue {
- msg = "got: \(actual) \(message.postfixActual)"
- } else {
- msg = "expected \(message.to) \(message.postfixMessage)"
- }
- recordFailure("\(msg)\n", location: location)
- }
- }
-}
-
-/// Fallback handler in case XCTest is unavailable. This assertion handler will abort
-/// the program if it is invoked.
-class NimbleXCTestUnavailableHandler: AssertionHandler {
- func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) {
- fatalError("XCTest is not available and no custom assertion handler was configured. Aborting.")
- }
-}
-
-#if !SWIFT_PACKAGE
-/// Helper class providing access to the currently executing XCTestCase instance, if any
-@objc final internal class CurrentTestCaseTracker: NSObject, XCTestObservation {
- @objc static let sharedInstance = CurrentTestCaseTracker()
-
- private(set) var currentTestCase: XCTestCase?
-
- private var stashed_swift_reportFatalErrorsToDebugger: Bool = false
-
- @objc func testCaseWillStart(_ testCase: XCTestCase) {
- #if swift(>=3.2)
- stashed_swift_reportFatalErrorsToDebugger = _swift_reportFatalErrorsToDebugger
- _swift_reportFatalErrorsToDebugger = false
- #endif
-
- currentTestCase = testCase
- }
-
- @objc func testCaseDidFinish(_ testCase: XCTestCase) {
- currentTestCase = nil
-
- #if swift(>=3.2)
- _swift_reportFatalErrorsToDebugger = stashed_swift_reportFatalErrorsToDebugger
- #endif
- }
-}
-#endif
-
-func isXCTestAvailable() -> Bool {
-#if canImport(Darwin)
- // XCTest is weakly linked and so may not be present
- return NSClassFromString("XCTestCase") != nil
-#else
- return true
-#endif
-}
-
-public func recordFailure(_ message: String, location: SourceLocation) {
-#if SWIFT_PACKAGE
- XCTFail("\(message)", file: location.file, line: location.line)
-#else
- if let testCase = CurrentTestCaseTracker.sharedInstance.currentTestCase {
- let line = Int(location.line)
- testCase.recordFailure(withDescription: message, inFile: location.file, atLine: line, expected: true)
- } else {
- let msg = """
- Attempted to report a test failure to XCTest while no test case was running. The failure was:
- \"\(message)\"
- It occurred at: \(location.file):\(location.line)
- """
- NSException(name: .internalInconsistencyException, reason: msg, userInfo: nil).raise()
- }
-#endif
-}
diff --git a/Pods/Nimble/Sources/Nimble/DSL+Wait.swift b/Pods/Nimble/Sources/Nimble/DSL+Wait.swift
deleted file mode 100644
index c049417..0000000
--- a/Pods/Nimble/Sources/Nimble/DSL+Wait.swift
+++ /dev/null
@@ -1,122 +0,0 @@
-import Dispatch
-import Foundation
-
-private enum ErrorResult {
- case exception(NSException)
- case error(Error)
- case none
-}
-
-/// Only classes, protocols, methods, properties, and subscript declarations can be
-/// bridges to Objective-C via the @objc keyword. This class encapsulates callback-style
-/// asynchronous waiting logic so that it may be called from Objective-C and Swift.
-internal class NMBWait: NSObject {
-// About these kind of lines, `@objc` attributes are only required for Objective-C
-// support, so that should be conditional on Darwin platforms and normal Xcode builds
-// (non-SwiftPM builds).
-#if canImport(Darwin) && !SWIFT_PACKAGE
- @objc
- internal class func until(
- timeout: TimeInterval,
- file: FileString = #file,
- line: UInt = #line,
- action: @escaping (@escaping () -> Void) -> Void) {
- return throwableUntil(timeout: timeout, file: file, line: line) { done in
- action(done)
- }
- }
-#else
- internal class func until(
- timeout: TimeInterval,
- file: FileString = #file,
- line: UInt = #line,
- action: @escaping (@escaping () -> Void) -> Void) {
- return throwableUntil(timeout: timeout, file: file, line: line) { done in
- action(done)
- }
- }
-#endif
-
- // Using a throwable closure makes this method not objc compatible.
- internal class func throwableUntil(
- timeout: TimeInterval,
- file: FileString = #file,
- line: UInt = #line,
- action: @escaping (@escaping () -> Void) throws -> Void) {
- let awaiter = NimbleEnvironment.activeInstance.awaiter
- let leeway = timeout / 2.0
- // swiftlint:disable:next line_length
- let result = awaiter.performBlock(file: file, line: line) { (done: @escaping (ErrorResult) -> Void) throws -> Void in
- DispatchQueue.main.async {
- let capture = NMBExceptionCapture(
- handler: ({ exception in
- done(.exception(exception))
- }),
- finally: ({ })
- )
- capture.tryBlock {
- do {
- try action {
- done(.none)
- }
- } catch let e {
- done(.error(e))
- }
- }
- }
- }.timeout(timeout, forcefullyAbortTimeout: leeway).wait("waitUntil(...)", file: file, line: line)
-
- switch result {
- case .incomplete: internalError("Reached .incomplete state for waitUntil(...).")
- case .blockedRunLoop:
- fail(blockedRunLoopErrorMessageFor("-waitUntil()", leeway: leeway),
- file: file, line: line)
- case .timedOut:
- let pluralize = (timeout == 1 ? "" : "s")
- fail("Waited more than \(timeout) second\(pluralize)", file: file, line: line)
- case let .raisedException(exception):
- fail("Unexpected exception raised: \(exception)")
- case let .errorThrown(error):
- fail("Unexpected error thrown: \(error)")
- case .completed(.exception(let exception)):
- fail("Unexpected exception raised: \(exception)")
- case .completed(.error(let error)):
- fail("Unexpected error thrown: \(error)")
- case .completed(.none): // success
- break
- }
- }
-
-#if canImport(Darwin) && !SWIFT_PACKAGE
- @objc(untilFile:line:action:)
- internal class func until(
- _ file: FileString = #file,
- line: UInt = #line,
- action: @escaping (@escaping () -> Void) -> Void) {
- until(timeout: 1, file: file, line: line, action: action)
- }
-#else
- internal class func until(
- _ file: FileString = #file,
- line: UInt = #line,
- action: @escaping (@escaping () -> Void) -> Void) {
- until(timeout: 1, file: file, line: line, action: action)
- }
-#endif
-}
-
-internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterval) -> String {
- // swiftlint:disable:next line_length
- return "\(fnName) timed out but was unable to run the timeout handler because the main thread is unresponsive (\(leeway) seconds is allow after the wait times out). Conditions that may cause this include processing blocking IO on the main thread, calls to sleep(), deadlocks, and synchronous IPC. Nimble forcefully stopped run loop which may cause future failures in test run."
-}
-
-/// Wait asynchronously until the done closure is called or the timeout has been reached.
-///
-/// @discussion
-/// Call the done() closure to indicate the waiting has completed.
-///
-/// This function manages the main run loop (`NSRunLoop.mainRunLoop()`) while this function
-/// is executing. Any attempts to touch the run loop may cause non-deterministic behavior.
-public func waitUntil(timeout: TimeInterval = AsyncDefaults.Timeout, file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) {
- NMBWait.until(timeout: timeout, file: file, line: line, action: action)
-}
diff --git a/Pods/Nimble/Sources/Nimble/DSL.swift b/Pods/Nimble/Sources/Nimble/DSL.swift
deleted file mode 100644
index d6dc9cc..0000000
--- a/Pods/Nimble/Sources/Nimble/DSL.swift
+++ /dev/null
@@ -1,68 +0,0 @@
-import Foundation
-
-/// Make an expectation on a given actual value. The value given is lazily evaluated.
-public func expect(_ expression: @autoclosure @escaping () throws -> T?, file: FileString = #file, line: UInt = #line) -> Expectation {
- return Expectation(
- expression: Expression(
- expression: expression,
- location: SourceLocation(file: file, line: line),
- isClosure: true))
-}
-
-/// Make an expectation on a given actual value. The closure is lazily invoked.
-public func expect(_ file: FileString = #file, line: UInt = #line, expression: @escaping () throws -> T?) -> Expectation {
- return Expectation(
- expression: Expression(
- expression: expression,
- location: SourceLocation(file: file, line: line),
- isClosure: true))
-}
-
-/// Always fails the test with a message and a specified location.
-public func fail(_ message: String, location: SourceLocation) {
- let handler = NimbleEnvironment.activeInstance.assertionHandler
- handler.assert(false, message: FailureMessage(stringValue: message), location: location)
-}
-
-/// Always fails the test with a message.
-public func fail(_ message: String, file: FileString = #file, line: UInt = #line) {
- fail(message, location: SourceLocation(file: file, line: line))
-}
-
-/// Always fails the test.
-public func fail(_ file: FileString = #file, line: UInt = #line) {
- fail("fail() always fails", file: file, line: line)
-}
-
-/// Like Swift's precondition(), but raises NSExceptions instead of sigaborts
-internal func nimblePrecondition(
- _ expr: @autoclosure() -> Bool,
- _ name: @autoclosure() -> String,
- _ message: @autoclosure() -> String,
- file: StaticString = #file,
- line: UInt = #line) {
- let result = expr()
- if !result {
-#if canImport(Darwin)
- let exception = NSException(
- name: NSExceptionName(name()),
- reason: message(),
- userInfo: nil
- )
- exception.raise()
-#else
- preconditionFailure("\(name()) - \(message())", file: file, line: line)
-#endif
- }
-}
-
-internal func internalError(_ msg: String, file: FileString = #file, line: UInt = #line) -> Never {
- // swiftlint:disable line_length
- fatalError(
- """
- Nimble Bug Found: \(msg) at \(file):\(line).
- Please file a bug to Nimble: https://github.com/Quick/Nimble/issues with the code snippet that caused this error.
- """
- )
- // swiftlint:enable line_length
-}
diff --git a/Pods/Nimble/Sources/Nimble/Expectation.swift b/Pods/Nimble/Sources/Nimble/Expectation.swift
deleted file mode 100644
index 41625a1..0000000
--- a/Pods/Nimble/Sources/Nimble/Expectation.swift
+++ /dev/null
@@ -1,125 +0,0 @@
-import Foundation
-
-// Deprecated
-internal func expressionDoesNotMatch(_ expression: Expression, matcher: U, toNot: String, description: String?) -> (Bool, FailureMessage)
- where U: Matcher, U.ValueType == T {
- let msg = FailureMessage()
- msg.userDescription = description
- msg.to = toNot
- do {
- let pass = try matcher.doesNotMatch(expression, failureMessage: msg)
- if msg.actualValue == "" {
- msg.actualValue = "<\(stringify(try expression.evaluate()))>"
- }
- return (pass, msg)
- } catch let error {
- msg.stringValue = "unexpected error thrown: <\(error)>"
- return (false, msg)
- }
-}
-
-internal func execute(_ expression: Expression, _ style: ExpectationStyle, _ predicate: Predicate, to: String, description: String?, captureExceptions: Bool = true) -> (Bool, FailureMessage) {
- func run() -> (Bool, FailureMessage) {
- let msg = FailureMessage()
- msg.userDescription = description
- msg.to = to
- do {
- let result = try predicate.satisfies(expression)
- result.message.update(failureMessage: msg)
- if msg.actualValue == "" {
- msg.actualValue = "<\(stringify(try expression.evaluate()))>"
- }
- return (result.toBoolean(expectation: style), msg)
- } catch let error {
- msg.stringValue = "unexpected error thrown: <\(error)>"
- return (false, msg)
- }
- }
-
- var result: (Bool, FailureMessage) = (false, FailureMessage())
- if captureExceptions {
- let capture = NMBExceptionCapture(handler: ({ exception -> Void in
- let msg = FailureMessage()
- msg.stringValue = "unexpected exception raised: \(exception)"
- result = (false, msg)
- }), finally: nil)
- capture.tryBlock {
- result = run()
- }
- } else {
- result = run()
- }
-
- return result
-}
-
-public struct Expectation {
-
- public let expression: Expression
-
- public init(expression: Expression) {
- self.expression = expression
- }
-
- public func verify(_ pass: Bool, _ message: FailureMessage) {
- let handler = NimbleEnvironment.activeInstance.assertionHandler
- handler.assert(pass, message: message, location: expression.location)
- }
-
- ////////////////// OLD API /////////////////////
-
- /// DEPRECATED: Tests the actual value using a matcher to match.
- public func to(_ matcher: U, description: String? = nil)
- where U: Matcher, U.ValueType == T {
- let (pass, msg) = execute(
- expression,
- .toMatch,
- matcher.predicate,
- to: "to",
- description: description,
- captureExceptions: false
- )
- verify(pass, msg)
- }
-
- /// DEPRECATED: Tests the actual value using a matcher to not match.
- public func toNot(_ matcher: U, description: String? = nil)
- where U: Matcher, U.ValueType == T {
- // swiftlint:disable:next line_length
- let (pass, msg) = expressionDoesNotMatch(expression, matcher: matcher, toNot: "to not", description: description)
- verify(pass, msg)
- }
-
- /// DEPRECATED: Tests the actual value using a matcher to not match.
- ///
- /// Alias to toNot().
- public func notTo(_ matcher: U, description: String? = nil)
- where U: Matcher, U.ValueType == T {
- toNot(matcher, description: description)
- }
-
- ////////////////// NEW API /////////////////////
-
- /// Tests the actual value using a matcher to match.
- public func to(_ predicate: Predicate, description: String? = nil) {
- let (pass, msg) = execute(expression, .toMatch, predicate, to: "to", description: description)
- verify(pass, msg)
- }
-
- /// Tests the actual value using a matcher to not match.
- public func toNot(_ predicate: Predicate, description: String? = nil) {
- let (pass, msg) = execute(expression, .toNotMatch, predicate, to: "to not", description: description)
- verify(pass, msg)
- }
-
- /// Tests the actual value using a matcher to not match.
- ///
- /// Alias to toNot().
- public func notTo(_ predicate: Predicate, description: String? = nil) {
- toNot(predicate, description: description)
- }
-
- // see:
- // - `async` for extension
- // - NMBExpectation for Objective-C interface
-}
diff --git a/Pods/Nimble/Sources/Nimble/ExpectationMessage.swift b/Pods/Nimble/Sources/Nimble/ExpectationMessage.swift
deleted file mode 100644
index b0cbcc3..0000000
--- a/Pods/Nimble/Sources/Nimble/ExpectationMessage.swift
+++ /dev/null
@@ -1,267 +0,0 @@
-import Foundation
-
-public indirect enum ExpectationMessage {
- // --- Primary Expectations ---
- /// includes actual value in output ("expected to , got ")
- case expectedActualValueTo(/* message: */ String)
- /// uses a custom actual value string in output ("expected to , got ")
- case expectedCustomValueTo(/* message: */ String, /* actual: */ String)
- /// excludes actual value in output ("expected to ")
- case expectedTo(/* message: */ String)
- /// allows any free-form message ("")
- case fail(/* message: */ String)
-
- // --- Composite Expectations ---
- // Generally, you'll want the methods, appended(message:) and appended(details:) instead.
-
- /// Not Fully Implemented Yet.
- case prepends(/* Prepended Message */ String, ExpectationMessage)
-
- /// appends after an existing message (" (use beNil() to match nils)")
- case appends(ExpectationMessage, /* Appended Message */ String)
-
- /// provides long-form multi-line explainations ("\n\n")
- case details(ExpectationMessage, String)
-
- internal var sampleMessage: String {
- let asStr = toString(actual: "", expected: "expected", to: "to")
- let asFailureMessage = FailureMessage()
- update(failureMessage: asFailureMessage)
- // swiftlint:disable:next line_length
- return "(toString(actual:expected:to:) -> \(asStr) || update(failureMessage:) -> \(asFailureMessage.stringValue))"
- }
-
- /// Returns the smallest message after the "expected to" string that summarizes the error.
- ///
- /// Returns the message part from ExpectationMessage, ignoring all .appends and .details.
- public var expectedMessage: String {
- switch self {
- case let .fail(msg):
- return msg
- case let .expectedTo(msg):
- return msg
- case let .expectedActualValueTo(msg):
- return msg
- case let .expectedCustomValueTo(msg, _):
- return msg
- case let .prepends(_, expectation):
- return expectation.expectedMessage
- case let .appends(expectation, msg):
- return "\(expectation.expectedMessage)\(msg)"
- case let .details(expectation, _):
- return expectation.expectedMessage
- }
- }
-
- /// Appends a message after the primary expectation message
- public func appended(message: String) -> ExpectationMessage {
- switch self {
- case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo, .appends, .prepends:
- return .appends(self, message)
- case let .details(expectation, msg):
- return .details(expectation.appended(message: message), msg)
- }
- }
-
- /// Appends a message hinting to use beNil() for when the actual value given was nil.
- public func appendedBeNilHint() -> ExpectationMessage {
- return appended(message: " (use beNil() to match nils)")
- }
-
- /// Appends a detailed (aka - multiline) message after the primary expectation message
- /// Detailed messages will be placed after .appended(message:) calls.
- public func appended(details: String) -> ExpectationMessage {
- return .details(self, details)
- }
-
- internal func visitLeafs(_ f: (ExpectationMessage) -> ExpectationMessage) -> ExpectationMessage {
- // swiftlint:disable:previous identifier_name
- switch self {
- case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo:
- return f(self)
- case let .prepends(msg, expectation):
- return .prepends(msg, expectation.visitLeafs(f))
- case let .appends(expectation, msg):
- return .appends(expectation.visitLeafs(f), msg)
- case let .details(expectation, msg):
- return .details(expectation.visitLeafs(f), msg)
- }
- }
-
- /// Replaces a primary expectation with one returned by f. Preserves all composite expectations
- /// that were built upon it (aka - all appended(message:) and appended(details:).
- public func replacedExpectation(_ f: @escaping (ExpectationMessage) -> ExpectationMessage) -> ExpectationMessage {
- // swiftlint:disable:previous identifier_name
- func walk(_ msg: ExpectationMessage) -> ExpectationMessage {
- switch msg {
- case .fail, .expectedTo, .expectedActualValueTo, .expectedCustomValueTo:
- return f(msg)
- default:
- return msg
- }
- }
- return visitLeafs(walk)
- }
-
- /// Wraps a primary expectation with text before and after it.
- /// Alias to prepended(message: before).appended(message: after)
- public func wrappedExpectation(before: String, after: String) -> ExpectationMessage {
- return prepended(expectation: before).appended(message: after)
- }
-
- /// Prepends a message by modifying the primary expectation
- public func prepended(expectation message: String) -> ExpectationMessage {
- func walk(_ msg: ExpectationMessage) -> ExpectationMessage {
- switch msg {
- case let .expectedTo(msg):
- return .expectedTo(message + msg)
- case let .expectedActualValueTo(msg):
- return .expectedActualValueTo(message + msg)
- case let .expectedCustomValueTo(msg, actual):
- return .expectedCustomValueTo(message + msg, actual)
- default:
- return msg.visitLeafs(walk)
- }
- }
- return visitLeafs(walk)
- }
-
- // swiftlint:disable:next todo
- // TODO: test & verify correct behavior
- internal func prepended(message: String) -> ExpectationMessage {
- return .prepends(message, self)
- }
-
- /// Converts the tree of ExpectationMessages into a final built string.
- public func toString(actual: String, expected: String = "expected", to: String = "to") -> String {
- switch self {
- case let .fail(msg):
- return msg
- case let .expectedTo(msg):
- return "\(expected) \(to) \(msg)"
- case let .expectedActualValueTo(msg):
- return "\(expected) \(to) \(msg), got \(actual)"
- case let .expectedCustomValueTo(msg, actual):
- return "\(expected) \(to) \(msg), got \(actual)"
- case let .prepends(msg, expectation):
- return "\(msg)\(expectation.toString(actual: actual, expected: expected, to: to))"
- case let .appends(expectation, msg):
- return "\(expectation.toString(actual: actual, expected: expected, to: to))\(msg)"
- case let .details(expectation, msg):
- return "\(expectation.toString(actual: actual, expected: expected, to: to))\n\n\(msg)"
- }
- }
-
- // Backwards compatibility: converts ExpectationMessage tree to FailureMessage
- internal func update(failureMessage: FailureMessage) {
- switch self {
- case let .fail(msg) where !msg.isEmpty:
- failureMessage.stringValue = msg
- case .fail:
- break
- case let .expectedTo(msg):
- failureMessage.actualValue = nil
- failureMessage.postfixMessage = msg
- case let .expectedActualValueTo(msg):
- failureMessage.postfixMessage = msg
- case let .expectedCustomValueTo(msg, actual):
- failureMessage.postfixMessage = msg
- failureMessage.actualValue = actual
- case let .prepends(msg, expectation):
- expectation.update(failureMessage: failureMessage)
- if let desc = failureMessage.userDescription {
- failureMessage.userDescription = "\(msg)\(desc)"
- } else {
- failureMessage.userDescription = msg
- }
- case let .appends(expectation, msg):
- expectation.update(failureMessage: failureMessage)
- failureMessage.appendMessage(msg)
- case let .details(expectation, msg):
- expectation.update(failureMessage: failureMessage)
- failureMessage.appendDetails(msg)
- }
- }
-}
-
-extension FailureMessage {
- internal func toExpectationMessage() -> ExpectationMessage {
- let defaultMessage = FailureMessage()
- if expected != defaultMessage.expected || _stringValueOverride != nil {
- return .fail(stringValue)
- }
-
- var message: ExpectationMessage = .fail(userDescription ?? "")
- if actualValue != "" && actualValue != nil {
- message = .expectedCustomValueTo(postfixMessage, actualValue ?? "")
- } else if postfixMessage != defaultMessage.postfixMessage {
- if actualValue == nil {
- message = .expectedTo(postfixMessage)
- } else {
- message = .expectedActualValueTo(postfixMessage)
- }
- }
- if postfixActual != defaultMessage.postfixActual {
- message = .appends(message, postfixActual)
- }
- if let extended = extendedMessage {
- message = .details(message, extended)
- }
- return message
- }
-}
-
-#if canImport(Darwin)
-
-public class NMBExpectationMessage: NSObject {
- private let msg: ExpectationMessage
-
- internal init(swift msg: ExpectationMessage) {
- self.msg = msg
- }
-
- public init(expectedTo message: String) {
- self.msg = .expectedTo(message)
- }
- public init(expectedActualValueTo message: String) {
- self.msg = .expectedActualValueTo(message)
- }
-
- public init(expectedActualValueTo message: String, customActualValue actual: String) {
- self.msg = .expectedCustomValueTo(message, actual)
- }
-
- public init(fail message: String) {
- self.msg = .fail(message)
- }
-
- public init(prepend message: String, child: NMBExpectationMessage) {
- self.msg = .prepends(message, child.msg)
- }
-
- public init(appendedMessage message: String, child: NMBExpectationMessage) {
- self.msg = .appends(child.msg, message)
- }
-
- public init(prependedMessage message: String, child: NMBExpectationMessage) {
- self.msg = .prepends(message, child.msg)
- }
-
- public init(details message: String, child: NMBExpectationMessage) {
- self.msg = .details(child.msg, message)
- }
-
- public func appendedBeNilHint() -> NMBExpectationMessage {
- return NMBExpectationMessage(swift: msg.appendedBeNilHint())
- }
-
- public func toSwift() -> ExpectationMessage { return self.msg }
-}
-
-extension ExpectationMessage {
- func toObjectiveC() -> NMBExpectationMessage {
- return NMBExpectationMessage(swift: self)
- }
-}
-
-#endif
diff --git a/Pods/Nimble/Sources/Nimble/Expression.swift b/Pods/Nimble/Sources/Nimble/Expression.swift
deleted file mode 100644
index dcc42e4..0000000
--- a/Pods/Nimble/Sources/Nimble/Expression.swift
+++ /dev/null
@@ -1,101 +0,0 @@
-import Foundation
-
-// Memoizes the given closure, only calling the passed
-// closure once; even if repeat calls to the returned closure
-internal func memoizedClosure(_ closure: @escaping () throws -> T) -> (Bool) throws -> T {
- var cache: T?
- return { withoutCaching in
- if withoutCaching || cache == nil {
- cache = try closure()
- }
- return cache!
- }
-}
-
-/// Expression represents the closure of the value inside expect(...).
-/// Expressions are memoized by default. This makes them safe to call
-/// evaluate() multiple times without causing a re-evaluation of the underlying
-/// closure.
-///
-/// @warning Since the closure can be any code, Objective-C code may choose
-/// to raise an exception. Currently, Expression does not memoize
-/// exception raising.
-///
-/// This provides a common consumable API for matchers to utilize to allow
-/// Nimble to change internals to how the captured closure is managed.
-public struct Expression {
- // swiftlint:disable identifier_name
- internal let _expression: (Bool) throws -> T?
- internal let _withoutCaching: Bool
- // swiftlint:enable identifier_name
- public let location: SourceLocation
- public let isClosure: Bool
-
- /// Creates a new expression struct. Normally, expect(...) will manage this
- /// creation process. The expression is memoized.
- ///
- /// @param expression The closure that produces a given value.
- /// @param location The source location that this closure originates from.
- /// @param isClosure A bool indicating if the captured expression is a
- /// closure or internally produced closure. Some matchers
- /// may require closures. For example, toEventually()
- /// requires an explicit closure. This gives Nimble
- /// flexibility if @autoclosure behavior changes between
- /// Swift versions. Nimble internals always sets this true.
- public init(expression: @escaping () throws -> T?, location: SourceLocation, isClosure: Bool = true) {
- self._expression = memoizedClosure(expression)
- self.location = location
- self._withoutCaching = false
- self.isClosure = isClosure
- }
-
- /// Creates a new expression struct. Normally, expect(...) will manage this
- /// creation process.
- ///
- /// @param expression The closure that produces a given value.
- /// @param location The source location that this closure originates from.
- /// @param withoutCaching Indicates if the struct should memoize the given
- /// closure's result. Subsequent evaluate() calls will
- /// not call the given closure if this is true.
- /// @param isClosure A bool indicating if the captured expression is a
- /// closure or internally produced closure. Some matchers
- /// may require closures. For example, toEventually()
- /// requires an explicit closure. This gives Nimble
- /// flexibility if @autoclosure behavior changes between
- /// Swift versions. Nimble internals always sets this true.
- public init(memoizedExpression: @escaping (Bool) throws -> T?, location: SourceLocation, withoutCaching: Bool, isClosure: Bool = true) {
- self._expression = memoizedExpression
- self.location = location
- self._withoutCaching = withoutCaching
- self.isClosure = isClosure
- }
-
- /// Returns a new Expression from the given expression. Identical to a map()
- /// on this type. This should be used only to typecast the Expression's
- /// closure value.
- ///
- /// The returned expression will preserve location and isClosure.
- ///
- /// @param block The block that can cast the current Expression value to a
- /// new type.
- public func cast(_ block: @escaping (T?) throws -> U?) -> Expression {
- return Expression(
- expression: ({ try block(self.evaluate()) }),
- location: self.location,
- isClosure: self.isClosure
- )
- }
-
- public func evaluate() throws -> T? {
- return try self._expression(_withoutCaching)
- }
-
- public func withoutCaching() -> Expression {
- return Expression(
- memoizedExpression: self._expression,
- location: location,
- withoutCaching: true,
- isClosure: isClosure
- )
- }
-}
diff --git a/Pods/Nimble/Sources/Nimble/FailureMessage.swift b/Pods/Nimble/Sources/Nimble/FailureMessage.swift
deleted file mode 100644
index 503b540..0000000
--- a/Pods/Nimble/Sources/Nimble/FailureMessage.swift
+++ /dev/null
@@ -1,93 +0,0 @@
-import Foundation
-
-/// Encapsulates the failure message that matchers can report to the end user.
-///
-/// This is shared state between Nimble and matchers that mutate this value.
-public class FailureMessage: NSObject {
- public var expected: String = "expected"
- public var actualValue: String? = "" // empty string -> use default; nil -> exclude
- public var to: String = "to"
- public var postfixMessage: String = "match"
- public var postfixActual: String = ""
- /// An optional message that will be appended as a new line and provides additional details
- /// about the failure. This message will only be visible in the issue navigator / in logs but
- /// not directly in the source editor since only a single line is presented there.
- public var extendedMessage: String?
- public var userDescription: String?
-
- public var stringValue: String {
- get {
- if let value = _stringValueOverride {
- return value
- } else {
- return computeStringValue()
- }
- }
- set {
- _stringValueOverride = newValue
- }
- }
-
- // swiftlint:disable:next identifier_name
- internal var _stringValueOverride: String?
- internal var hasOverriddenStringValue: Bool {
- return _stringValueOverride != nil
- }
-
- public override init() {
- }
-
- public init(stringValue: String) {
- _stringValueOverride = stringValue
- }
-
- internal func stripNewlines(_ str: String) -> String {
- let whitespaces = CharacterSet.whitespacesAndNewlines
- return str
- .components(separatedBy: "\n")
- .map { line in line.trimmingCharacters(in: whitespaces) }
- .joined(separator: "")
- }
-
- internal func computeStringValue() -> String {
- var value = "\(expected) \(to) \(postfixMessage)"
- if let actualValue = actualValue {
- value = "\(expected) \(to) \(postfixMessage), got \(actualValue)\(postfixActual)"
- }
- value = stripNewlines(value)
-
- if let extendedMessage = extendedMessage {
- value += "\n\(stripNewlines(extendedMessage))"
- }
-
- if let userDescription = userDescription {
- return "\(userDescription)\n\(value)"
- }
-
- return value
- }
-
- internal func appendMessage(_ msg: String) {
- if hasOverriddenStringValue {
- stringValue += "\(msg)"
- } else if actualValue != nil {
- postfixActual += msg
- } else {
- postfixMessage += msg
- }
- }
-
- internal func appendDetails(_ msg: String) {
- if hasOverriddenStringValue {
- if let desc = userDescription {
- stringValue = "\(desc)\n\(stringValue)"
- }
- stringValue += "\n\(msg)"
- } else {
- if let desc = userDescription {
- userDescription = desc
- }
- extendedMessage = msg
- }
- }
-}
diff --git a/Pods/Nimble/Sources/Nimble/Matchers/AllPass.swift b/Pods/Nimble/Sources/Nimble/Matchers/AllPass.swift
deleted file mode 100644
index dbbccb9..0000000
--- a/Pods/Nimble/Sources/Nimble/Matchers/AllPass.swift
+++ /dev/null
@@ -1,122 +0,0 @@
-import Foundation
-
-public func allPass
- (_ passFunc: @escaping (T?) throws -> Bool) -> Predicate
- where U: Sequence, T == U.Iterator.Element {
- let matcher = Predicate.simpleNilable("pass a condition") { actualExpression in
- return PredicateStatus(bool: try passFunc(try actualExpression.evaluate()))
- }
- return createPredicate(matcher)
-}
-
-public func allPass
- (_ passName: String, _ passFunc: @escaping (T?) throws -> Bool) -> Predicate
- where U: Sequence, T == U.Iterator.Element {
- let matcher = Predicate.simpleNilable(passName) { actualExpression in
- return PredicateStatus(bool: try passFunc(try actualExpression.evaluate()))
- }
- return createPredicate(matcher)
-}
-
-public func allPass(_ elementMatcher: M) -> Predicate
- where S: Sequence, M: Matcher, S.Iterator.Element == M.ValueType {
- return createPredicate(elementMatcher.predicate)
-}
-
-public func allPass(_ elementPredicate: Predicate) -> Predicate
- where S: Sequence {
- return createPredicate(elementPredicate)
-}
-
-private func createPredicate(_ elementMatcher: Predicate