diff --git a/InstantSearch.podspec b/InstantSearch.podspec
index 7204c4cd..a7ea1126 100644
--- a/InstantSearch.podspec
+++ b/InstantSearch.podspec
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "InstantSearch"
s.module_name = 'InstantSearch'
- s.version = "5.0.0"
+ s.version = "5.1.0"
s.summary = "A library of widgets and helpers to build instant-search applications on iOS."
s.homepage = "https://github.com/algolia/instantsearch-ios"
s.license = { type: 'Apache 2.0', file: 'LICENSE.md' }
diff --git a/InstantSearchTestsHost/Info.plist b/InstantSearchTestsHost/Info.plist
index ee3c849e..0288e224 100644
--- a/InstantSearchTestsHost/Info.plist
+++ b/InstantSearchTestsHost/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 4.0.0
+ 5.1.0
CFBundleVersion
1
LSRequiresIPhoneOS
diff --git a/Sources/Controller/Hits/CollectionView/HitsCollectionController.swift b/Sources/Controller/Hits/CollectionView/HitsCollectionController.swift
index 6c89d300..7da199ea 100644
--- a/Sources/Controller/Hits/CollectionView/HitsCollectionController.swift
+++ b/Sources/Controller/Hits/CollectionView/HitsCollectionController.swift
@@ -22,14 +22,14 @@ public class HitsCollectionController: NSObject, HitsControl
public weak var hitsSource: Source?
- private var dataSource: HitsCollectionViewDataSource? {
+ public var dataSource: HitsCollectionViewDataSource? {
didSet {
dataSource?.hitsSource = hitsSource
collectionView.dataSource = dataSource
}
}
- private var delegate: HitsCollectionViewDelegate? {
+ public var delegate: HitsCollectionViewDelegate? {
didSet {
delegate?.hitsSource = hitsSource
collectionView.delegate = delegate
diff --git a/Sources/Controller/Hits/CollectionView/HitsCollectionViewDataSource.swift b/Sources/Controller/Hits/CollectionView/HitsCollectionViewDataSource.swift
index 23a1fced..8c254373 100644
--- a/Sources/Controller/Hits/CollectionView/HitsCollectionViewDataSource.swift
+++ b/Sources/Controller/Hits/CollectionView/HitsCollectionViewDataSource.swift
@@ -11,21 +11,36 @@ import UIKit
open class HitsCollectionViewDataSource: NSObject, UICollectionViewDataSource {
public var cellConfigurator: CollectionViewCellConfigurator
+ public var templateCellProvider: () -> UICollectionViewCell
public weak var hitsSource: DataSource?
public init(cellConfigurator: @escaping CollectionViewCellConfigurator) {
self.cellConfigurator = cellConfigurator
+ self.templateCellProvider = { return .init() }
}
open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
- return hitsSource?.numberOfHits() ?? 0
+
+ guard let hitsSource = hitsSource else {
+ fatalError("Missing hits source")
+ }
+
+ return hitsSource.numberOfHits()
+
}
open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
- guard let hit = hitsSource?.hit(atIndex: indexPath.row) else {
- return UICollectionViewCell()
+
+ guard let hitsSource = hitsSource else {
+ fatalError("Missing hits source")
+ }
+
+ guard let hit = hitsSource.hit(atIndex: indexPath.row) else {
+ return templateCellProvider()
}
+
return cellConfigurator(collectionView, hit, indexPath)
+
}
}
diff --git a/Sources/Controller/Hits/CollectionView/HitsCollectionViewDelegate.swift b/Sources/Controller/Hits/CollectionView/HitsCollectionViewDelegate.swift
index a42e35c9..90b65d4a 100644
--- a/Sources/Controller/Hits/CollectionView/HitsCollectionViewDelegate.swift
+++ b/Sources/Controller/Hits/CollectionView/HitsCollectionViewDelegate.swift
@@ -18,10 +18,16 @@ open class HitsCollectionViewDelegate: NSObject, UIColle
}
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
- guard let hit = hitsSource?.hit(atIndex: indexPath.row) else {
+
+ guard let hitsSource = hitsSource else {
+ fatalError("Missing hits source")
+ }
+
+ guard let hit = hitsSource.hit(atIndex: indexPath.row) else {
return
}
clickHandler(collectionView, hit, indexPath)
+
}
}
diff --git a/Sources/Controller/Hits/TableView/HitsTableViewDataSource.swift b/Sources/Controller/Hits/TableView/HitsTableViewDataSource.swift
index 6024931c..d8f0ec7d 100644
--- a/Sources/Controller/Hits/TableView/HitsTableViewDataSource.swift
+++ b/Sources/Controller/Hits/TableView/HitsTableViewDataSource.swift
@@ -11,21 +11,36 @@ import UIKit
open class HitsTableViewDataSource: NSObject, UITableViewDataSource {
public var cellConfigurator: TableViewCellConfigurator
+ public var templateCellProvider: () -> UITableViewCell
public weak var hitsSource: DataSource?
public init(cellConfigurator: @escaping TableViewCellConfigurator) {
self.cellConfigurator = cellConfigurator
+ self.templateCellProvider = { return .init() }
}
open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- return hitsSource?.numberOfHits() ?? 0
+
+ guard let hitsSource = hitsSource else {
+ fatalError("Missing hits source")
+ }
+
+ return hitsSource.numberOfHits()
+
}
open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- guard let hit = hitsSource?.hit(atIndex: indexPath.row) else {
- return UITableViewCell()
+
+ guard let hitsSource = hitsSource else {
+ fatalError("Missing hits source")
+ }
+
+ guard let hit = hitsSource.hit(atIndex: indexPath.row) else {
+ return templateCellProvider()
}
+
return cellConfigurator(tableView, hit, indexPath)
+
}
}
diff --git a/Sources/Controller/Hits/TableView/HitsTableViewDelegate.swift b/Sources/Controller/Hits/TableView/HitsTableViewDelegate.swift
index f87d450b..9be28033 100644
--- a/Sources/Controller/Hits/TableView/HitsTableViewDelegate.swift
+++ b/Sources/Controller/Hits/TableView/HitsTableViewDelegate.swift
@@ -18,10 +18,16 @@ open class HitsTableViewDelegate: NSObject, UITableViewD
}
open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- guard let hit = hitsSource?.hit(atIndex: indexPath.row) else {
+
+ guard let hitsSource = hitsSource else {
+ fatalError("Missing hits source")
+ }
+
+ guard let hit = hitsSource.hit(atIndex: indexPath.row) else {
return
}
clickHandler(tableView, hit, indexPath)
+
}
}
diff --git a/Sources/Controller/MultiIndexHits/CollectionView/MultiIndexHitsCollectionController.swift b/Sources/Controller/MultiIndexHits/CollectionView/MultiIndexHitsCollectionController.swift
index 3dbf171a..7659abd2 100644
--- a/Sources/Controller/MultiIndexHits/CollectionView/MultiIndexHitsCollectionController.swift
+++ b/Sources/Controller/MultiIndexHits/CollectionView/MultiIndexHitsCollectionController.swift
@@ -16,21 +16,21 @@ public class MultiIndexHitsCollectionController: NSObject, MultiIndexHitsControl
public weak var hitsSource: MultiIndexHitsSource? {
didSet {
- dataSource?.hitsDataSource = hitsSource
- delegate?.hitsDataSource = hitsSource
+ dataSource?.hitsSource = hitsSource
+ delegate?.hitsSource = hitsSource
}
}
public var dataSource: MultiIndexHitsCollectionViewDataSource? {
didSet {
- dataSource?.hitsDataSource = hitsSource
+ dataSource?.hitsSource = hitsSource
collectionView.dataSource = dataSource
}
}
public var delegate: MultiIndexHitsCollectionViewDelegate? {
didSet {
- delegate?.hitsDataSource = hitsSource
+ delegate?.hitsSource = hitsSource
collectionView.delegate = delegate
}
}
diff --git a/Sources/Controller/MultiIndexHits/CollectionView/MultiIndexHitsCollectionViewDataSource.swift b/Sources/Controller/MultiIndexHits/CollectionView/MultiIndexHitsCollectionViewDataSource.swift
index c415d62c..abe2b5de 100644
--- a/Sources/Controller/MultiIndexHits/CollectionView/MultiIndexHitsCollectionViewDataSource.swift
+++ b/Sources/Controller/MultiIndexHits/CollectionView/MultiIndexHitsCollectionViewDataSource.swift
@@ -12,7 +12,7 @@ open class MultiIndexHitsCollectionViewDataSource: NSObject {
private typealias CellConfigurator = (UICollectionView, Int) throws -> UICollectionViewCell
- public weak var hitsDataSource: MultiIndexHitsSource?
+ public weak var hitsSource: MultiIndexHitsSource?
private var cellConfigurators: [Int: CellConfigurator]
@@ -21,14 +21,23 @@ open class MultiIndexHitsCollectionViewDataSource: NSObject {
super.init()
}
- public func setCellConfigurator(forSection section: Int, _ cellConfigurator: @escaping CollectionViewCellConfigurator) {
+ public func setCellConfigurator(forSection section: Int,
+ templateCellProvider: @escaping () -> UICollectionViewCell = { return .init() },
+ _ cellConfigurator: @escaping CollectionViewCellConfigurator) {
cellConfigurators[section] = { [weak self] (collectionView, row) in
- guard let dataSource = self?.hitsDataSource else { return UICollectionViewCell() }
- guard let hit: Hit = try dataSource.hit(atIndex: row, inSection: section) else {
- assertionFailure("Invalid state: Attempt to deqeue a cell for a missing hit in a hits Interactor")
- return UICollectionViewCell()
+ guard let dataSource = self else {
+ return .init()
}
- return cellConfigurator(collectionView, hit, IndexPath(item: row, section: section))
+
+ guard let hitsSource = dataSource.hitsSource else {
+ fatalError("Missing hits source")
+ }
+
+ guard let hit: Hit = try hitsSource.hit(atIndex: row, inSection: section) else {
+ return templateCellProvider()
+ }
+
+ return cellConfigurator(collectionView, hit, IndexPath(row: row, section: section))
}
}
@@ -37,22 +46,25 @@ open class MultiIndexHitsCollectionViewDataSource: NSObject {
extension MultiIndexHitsCollectionViewDataSource: UICollectionViewDataSource {
open func numberOfSections(in collectionView: UICollectionView) -> Int {
- guard let numberOfSections = hitsDataSource?.numberOfSections() else {
- return 0
+ guard let hitsSource = hitsSource else {
+ fatalError("Missing hits source")
}
- return numberOfSections
+ return hitsSource.numberOfSections()
}
open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
- guard let numberOfRows = hitsDataSource?.numberOfHits(inSection: section) else {
- return 0
+ guard let hitsSource = hitsSource else {
+ fatalError("Missing hits source")
}
- return numberOfRows
+ return hitsSource.numberOfHits(inSection: section)
}
open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+ guard let cellConfigurator = cellConfigurators[indexPath.section] else {
+ fatalError("No cell configurator found for section \(indexPath.section)")
+ }
do {
- return try cellConfigurators[indexPath.section]?(collectionView, indexPath.row) ?? UICollectionViewCell()
+ return try cellConfigurator(collectionView, indexPath.row)
} catch let error {
fatalError("\(error)")
}
diff --git a/Sources/Controller/MultiIndexHits/CollectionView/MultiIndexHitsCollectionViewDelegate.swift b/Sources/Controller/MultiIndexHits/CollectionView/MultiIndexHitsCollectionViewDelegate.swift
index 7bce3f25..9f0272ab 100644
--- a/Sources/Controller/MultiIndexHits/CollectionView/MultiIndexHitsCollectionViewDelegate.swift
+++ b/Sources/Controller/MultiIndexHits/CollectionView/MultiIndexHitsCollectionViewDelegate.swift
@@ -12,7 +12,7 @@ open class MultiIndexHitsCollectionViewDelegate: NSObject {
typealias ClickHandler = (UICollectionView, Int) throws -> Void
- public weak var hitsDataSource: MultiIndexHitsSource?
+ public weak var hitsSource: MultiIndexHitsSource?
private var clickHandlers: [Int: ClickHandler]
@@ -23,11 +23,18 @@ open class MultiIndexHitsCollectionViewDelegate: NSObject {
public func setClickHandler(forSection section: Int, _ clickHandler: @escaping CollectionViewClickHandler) {
clickHandlers[section] = { [weak self] (collectionView, row) in
- guard let hit: Hit = try self?.hitsDataSource?.hit(atIndex: row, inSection: section) else {
- assertionFailure("Invalid state: Attempt to process a click of a cell for a missing hit in a hits Interactor")
+ guard let delegate = self else { return }
+
+ guard let hitsSource = delegate.hitsSource else {
+ fatalError("Missing hits source")
+ }
+
+ guard let hit: Hit = try hitsSource.hit(atIndex: row, inSection: section) else {
return
}
+
clickHandler(collectionView, hit, IndexPath(item: row, section: section))
+
}
}
@@ -36,8 +43,11 @@ open class MultiIndexHitsCollectionViewDelegate: NSObject {
extension MultiIndexHitsCollectionViewDelegate: UICollectionViewDelegate {
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+ guard let clickHandler = clickHandlers[indexPath.section] else {
+ fatalError("No click handler found for section \(indexPath.section)")
+ }
do {
- try clickHandlers[indexPath.section]?(collectionView, indexPath.row)
+ try clickHandler(collectionView, indexPath.row)
} catch let error {
fatalError("\(error)")
}
diff --git a/Sources/Controller/MultiIndexHits/TableView/MultiIndexHitsTableViewDataSource.swift b/Sources/Controller/MultiIndexHits/TableView/MultiIndexHitsTableViewDataSource.swift
index 0b4687a7..c25aedc5 100644
--- a/Sources/Controller/MultiIndexHits/TableView/MultiIndexHitsTableViewDataSource.swift
+++ b/Sources/Controller/MultiIndexHits/TableView/MultiIndexHitsTableViewDataSource.swift
@@ -21,12 +21,22 @@ open class MultiIndexHitsTableViewDataSource: NSObject {
super.init()
}
- public func setCellConfigurator(forSection section: Int, _ cellConfigurator: @escaping TableViewCellConfigurator) {
+ public func setCellConfigurator(forSection section: Int,
+ templateCellProvider: @escaping () -> UITableViewCell = { return .init() },
+ _ cellConfigurator: @escaping TableViewCellConfigurator) {
cellConfigurators[section] = { [weak self] (tableView, row) in
- guard let hit: Hit = try self?.hitsSource?.hit(atIndex: row, inSection: section) else {
- assertionFailure("Invalid state: Attempt to deqeue a cell for a missing hit in a hits Interactor")
- return UITableViewCell()
+ guard let dataSource = self else {
+ return .init()
}
+
+ guard let hitsSource = dataSource.hitsSource else {
+ fatalError("Missing hits source")
+ }
+
+ guard let hit: Hit = try hitsSource.hit(atIndex: row, inSection: section) else {
+ return templateCellProvider()
+ }
+
return cellConfigurator(tableView, hit, IndexPath(row: row, section: section))
}
}
@@ -36,22 +46,25 @@ open class MultiIndexHitsTableViewDataSource: NSObject {
extension MultiIndexHitsTableViewDataSource: UITableViewDataSource {
open func numberOfSections(in tableView: UITableView) -> Int {
- guard let numberOfSections = hitsSource?.numberOfSections() else {
- return 0
+ guard let hitsSource = hitsSource else {
+ fatalError("Missing hits source")
}
- return numberOfSections
+ return hitsSource.numberOfSections()
}
open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
- guard let numberOfRows = hitsSource?.numberOfHits(inSection: section) else {
- return 0
+ guard let hitsSource = hitsSource else {
+ fatalError("Missing hits source")
}
- return numberOfRows
+ return hitsSource.numberOfHits(inSection: section)
}
open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ guard let cellConfigurator = cellConfigurators[indexPath.section] else {
+ fatalError("No cell configurator found for section \(indexPath.section)")
+ }
do {
- return try cellConfigurators[indexPath.section]?(tableView, indexPath.row) ?? UITableViewCell()
+ return try cellConfigurator(tableView, indexPath.row)
} catch let error {
fatalError("\(error)")
}
diff --git a/Sources/Controller/MultiIndexHits/TableView/MultiIndexHitsTableViewDelegate.swift b/Sources/Controller/MultiIndexHits/TableView/MultiIndexHitsTableViewDelegate.swift
index b640bf2c..35856795 100644
--- a/Sources/Controller/MultiIndexHits/TableView/MultiIndexHitsTableViewDelegate.swift
+++ b/Sources/Controller/MultiIndexHits/TableView/MultiIndexHitsTableViewDelegate.swift
@@ -23,11 +23,18 @@ open class MultiIndexHitsTableViewDelegate: NSObject {
public func setClickHandler(forSection section: Int, _ clickHandler: @escaping TableViewClickHandler) {
clickHandlers[section] = { [weak self] (tableView, row) in
- guard let hit: Hit = try self?.hitsSource?.hit(atIndex: row, inSection: section) else {
- assertionFailure("Invalid state: Attempt to process a click of a cell for a missing hit in a hits Interactor")
+ guard let delegate = self else { return }
+
+ guard let hitsSource = delegate.hitsSource else {
+ fatalError("Missing hits source")
+ }
+
+ guard let hit: Hit = try hitsSource.hit(atIndex: row, inSection: section) else {
return
}
- clickHandler(tableView, hit, IndexPath(row: row, section: section))
+
+ clickHandler(tableView, hit, IndexPath(item: row, section: section))
+
}
}
@@ -36,8 +43,11 @@ open class MultiIndexHitsTableViewDelegate: NSObject {
extension MultiIndexHitsTableViewDelegate: UITableViewDelegate {
open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+ guard let clickHandler = clickHandlers[indexPath.section] else {
+ fatalError("No click handler found for section \(indexPath.section)")
+ }
do {
- try clickHandlers[indexPath.section]?(tableView, indexPath.row)
+ try clickHandler(tableView, indexPath.row)
} catch let error {
fatalError("\(error)")
}
diff --git a/Sources/FatalErrorUtil.swift b/Sources/FatalErrorUtil.swift
new file mode 100644
index 00000000..9038fab3
--- /dev/null
+++ b/Sources/FatalErrorUtil.swift
@@ -0,0 +1,41 @@
+//
+// FatalErrorUtil.swift
+// InstantSearch
+//
+// Created by Vladislav Fitc on 04/09/2019.
+//
+
+import Foundation
+
+// overrides Swift global `fatalError`
+public func fatalError(_ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) -> Never {
+ FatalErrorUtil.fatalErrorClosure(message(), file, line)
+ unreachable()
+}
+
+/// This is a `noreturn` function that pauses forever
+public func unreachable() -> Never {
+ repeat {
+ RunLoop.current.run()
+ } while (true)
+}
+
+/// Utility functions that can replace and restore the `fatalError` global function.
+public struct FatalErrorUtil {
+
+ // Called by the custom implementation of `fatalError`.
+ static var fatalErrorClosure: (String, StaticString, UInt) -> Never = defaultFatalErrorClosure
+
+ // backup of the original Swift `fatalError`
+ private static let defaultFatalErrorClosure = { Swift.fatalError($0, file: $1, line: $2) }
+
+ /// Replace the `fatalError` global function with something else.
+ public static func replaceFatalError(closure: @escaping (String, StaticString, UInt) -> Never) {
+ fatalErrorClosure = closure
+ }
+
+ /// Restore the `fatalError` global function back to the original Swift implementation
+ public static func restoreFatalError() {
+ fatalErrorClosure = defaultFatalErrorClosure
+ }
+}
diff --git a/Sources/Info.plist b/Sources/Info.plist
index 60b9c008..5313a0db 100644
--- a/Sources/Info.plist
+++ b/Sources/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 1.0.0
+ 5.1.0
CFBundleSignature
????
CFBundleVersion
diff --git a/Tests/CollectionViewHitsControllerTests.swift b/Tests/CollectionViewHitsControllerTests.swift
new file mode 100644
index 00000000..69798bc9
--- /dev/null
+++ b/Tests/CollectionViewHitsControllerTests.swift
@@ -0,0 +1,133 @@
+//
+// CollectionViewHitsControllerTests.swift
+// InstantSearchTests
+//
+// Created by Vladislav Fitc on 04/09/2019.
+//
+
+@testable import InstantSearch
+import Foundation
+import XCTest
+
+
+class TestTemplateCollectionViewCell: UICollectionViewCell {}
+
+class CollectionViewHitsControllerTests: XCTestCase {
+
+ func testMissingDataSource() {
+
+ let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
+
+ let dataSource = HitsCollectionViewDataSource { (_, hit, _) in
+ let cell = TestCollectionViewCell()
+ cell.content = hit
+ return cell
+ }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ _ = dataSource.collectionView(collectionView, cellForItemAt: .init())
+ }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ _ = dataSource.collectionView(collectionView, numberOfItemsInSection: .init())
+ }
+
+ let delegate = HitsCollectionViewDelegate { _,_,_ in }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ _ = delegate.collectionView(collectionView, didSelectItemAt: .init())
+ }
+
+ }
+
+ func testTemplate() {
+
+ let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
+
+ let hitsDataSource = TestHitsSource(hits: ["t1", "t2", "t3"])
+
+ let dataSource = HitsCollectionViewDataSource { (_, hit, _) -> UICollectionViewCell in
+ let cell = TestCollectionViewCell()
+ cell.content = hit
+ return cell
+ }
+
+ dataSource.hitsSource = hitsDataSource
+
+ dataSource.templateCellProvider = { return TestTemplateCollectionViewCell() }
+
+ XCTAssert(dataSource.collectionView(collectionView, cellForItemAt: IndexPath(item: 4, section: 0)) is TestTemplateCollectionViewCell, "")
+
+ }
+
+ func testDataSource() {
+
+ let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
+
+ let dataSource = HitsCollectionViewDataSource { (_, hit, _) -> UICollectionViewCell in
+ let cell = TestCollectionViewCell()
+ cell.content = hit
+ return cell
+ }
+
+ let hitsDataSource = TestHitsSource(hits: ["t1", "t2", "t3"])
+
+ dataSource.hitsSource = hitsDataSource
+
+ XCTAssertEqual(dataSource.collectionView(collectionView, numberOfItemsInSection: 0), 3)
+ XCTAssertEqual((dataSource.collectionView(collectionView, cellForItemAt: IndexPath(item: 1, section: 0)) as? TestCollectionViewCell)?.content, "t2")
+
+ }
+
+ func testDelegate() {
+
+ let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
+
+ let itemToSelect = 2
+
+ let hitsDataSource = TestHitsSource(hits: ["t1", "t2", "t3"])
+
+ let exp = expectation(description: "Hit selection")
+
+ let delegate = HitsCollectionViewDelegate { (_, hit, _) in
+ XCTAssertEqual(hit, hitsDataSource.hits[itemToSelect])
+ exp.fulfill()
+ }
+
+ delegate.hitsSource = hitsDataSource
+
+ delegate.collectionView(collectionView, didSelectItemAt: IndexPath(item: itemToSelect, section: 0))
+
+ waitForExpectations(timeout: 1, handler: .none)
+
+ }
+
+ func testWidget() {
+
+ let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
+
+ let vm = HitsInteractor()
+
+ let dataSource = HitsCollectionViewDataSource> { (_, hit, _) -> UICollectionViewCell in
+ let cell = TestCollectionViewCell()
+ cell.content = hit
+ return cell
+ }
+
+ dataSource.hitsSource = vm
+
+ let delegate = HitsCollectionViewDelegate> { (_, _, _) in }
+
+ delegate.hitsSource = vm
+
+ let widget = HitsCollectionController>(collectionView: collectionView)
+
+ widget.dataSource = dataSource
+ widget.delegate = delegate
+
+ XCTAssertTrue(collectionView.delegate === delegate)
+ XCTAssertTrue(collectionView.dataSource === dataSource)
+
+ }
+
+}
diff --git a/Tests/CollectionViewMultiIndexHitsControllerTests.swift b/Tests/CollectionViewMultiIndexHitsControllerTests.swift
new file mode 100644
index 00000000..bf80dc25
--- /dev/null
+++ b/Tests/CollectionViewMultiIndexHitsControllerTests.swift
@@ -0,0 +1,119 @@
+//
+// CollectionViewMultiIndexHitsControllerTests.swift
+// InstantSearch
+//
+// Created by Vladislav Fitc on 04/09/2019.
+//
+
+import Foundation
+
+@testable import InstantSearch
+import InstantSearchCore
+import Foundation
+import XCTest
+
+class TestCollectionViewCell: UICollectionViewCell {
+ var content: String?
+}
+
+class CollectionViewMultiIndexHitsControllerTests: XCTestCase {
+
+ func testDataSource() {
+
+ let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
+
+ let hitsSource = TestMultiHitsDataSource(hitsBySection: [["t11", "t12"], ["t21", "t22", "t23"]])
+
+ let dataSource = MultiIndexHitsCollectionViewDataSource()
+
+ dataSource.setCellConfigurator(forSection: 0) { (_, h: String, _) in
+ let cell = TestCollectionViewCell()
+ cell.content = h
+ return cell
+ }
+
+ dataSource.hitsSource = hitsSource
+
+ XCTAssertEqual(dataSource.numberOfSections(in: collectionView), 2)
+ XCTAssertEqual(dataSource.collectionView(collectionView, numberOfItemsInSection: 0), 2)
+
+ }
+
+ func testDelegate() {
+
+ let hitsSource = TestMultiHitsDataSource(hitsBySection: [["t11", "t12"], ["t21", "t22", "t23"]])
+
+ let delegate = MultiIndexHitsTableViewDelegate()
+ delegate.hitsSource = hitsSource
+
+ }
+
+ func testMissingHitsSource() {
+
+ let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
+
+ let dataSource = MultiIndexHitsCollectionViewDataSource()
+
+ dataSource.setCellConfigurator(forSection: 0) { (_, h: String, _) in
+ let cell = TestCollectionViewCell()
+ cell.content = h
+ return cell
+ }
+
+ let delegate = MultiIndexHitsCollectionViewDelegate()
+
+ delegate.setClickHandler(forSection: 0) { (_, h: String, _) in
+ }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ _ = dataSource.numberOfSections(in: collectionView)
+ }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ _ = dataSource.collectionView(collectionView, numberOfItemsInSection: 0)
+ }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ _ = dataSource.collectionView(collectionView, cellForItemAt: IndexPath(item: 0, section: 0))
+ }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ delegate.collectionView(collectionView, didSelectItemAt: IndexPath(item: 0, section: 0))
+ }
+
+ }
+
+
+ func testMissingCellHandler() {
+
+ let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
+
+ let dataSource = MultiIndexHitsCollectionViewDataSource()
+
+ let hitsSource = TestMultiHitsDataSource(hitsBySection: [["t11", "t12"], ["t21", "t22", "t23"]])
+
+ dataSource.hitsSource = hitsSource
+
+ expectFatalError(expectedMessage: "No cell configurator found for section 0") {
+ _ = dataSource.collectionView(collectionView, cellForItemAt: IndexPath(item: 0, section: 0))
+ }
+
+ }
+
+ func testMissingClickHandler() {
+
+ let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
+
+ let delegate = MultiIndexHitsCollectionViewDelegate()
+
+ let hitsSource = TestMultiHitsDataSource(hitsBySection: [["t11", "t12"], ["t21", "t22", "t23"]])
+
+ delegate.hitsSource = hitsSource
+
+ expectFatalError(expectedMessage: "No click handler found for section 0") {
+ _ = delegate.collectionView(collectionView, didSelectItemAt: IndexPath(row: 0, section: 0))
+ }
+
+ }
+
+}
diff --git a/Tests/FatalErrorTest.swift b/Tests/FatalErrorTest.swift
new file mode 100644
index 00000000..b0ac9401
--- /dev/null
+++ b/Tests/FatalErrorTest.swift
@@ -0,0 +1,38 @@
+//
+// FatalErrorTest.swift
+// InstantSearch
+//
+// Created by Vladislav Fitc on 04/09/2019.
+//
+
+@testable import InstantSearch
+import Foundation
+import XCTest
+
+extension XCTestCase {
+
+ func expectFatalError(expectedMessage: String, testcase: @escaping () -> Void) {
+
+ // arrange
+ let expectation = self.expectation(description: "expectingFatalError")
+ var assertionMessage: String? = nil
+
+ // override fatalError. This will pause forever when fatalError is called.
+ FatalErrorUtil.replaceFatalError { message, _, _ in
+ assertionMessage = message
+ expectation.fulfill()
+ unreachable()
+ }
+
+ // act, perform on separate thead because a call to fatalError pauses forever
+ DispatchQueue.global(qos: .userInitiated).async(execute: testcase)
+
+ waitForExpectations(timeout: 10) { _ in
+ // assert
+ XCTAssertEqual(assertionMessage, expectedMessage)
+
+ // clean up
+ FatalErrorUtil.restoreFatalError()
+ }
+ }
+}
diff --git a/Tests/Info.plist b/Tests/Info.plist
index 18f6dd6b..48f7188c 100644
--- a/Tests/Info.plist
+++ b/Tests/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 4.0.0
+ 5.1.0
CFBundleSignature
????
CFBundleVersion
diff --git a/Tests/TableViewHitsControllerTests.swift b/Tests/TableViewHitsControllerTests.swift
index be392e74..bb8a188e 100644
--- a/Tests/TableViewHitsControllerTests.swift
+++ b/Tests/TableViewHitsControllerTests.swift
@@ -10,27 +10,55 @@ import InstantSearchCore
import Foundation
import XCTest
-class TestHitsSource: HitsSource {
-
- typealias Hit = String
+class TestTemplateCell: UITableViewCell {}
- let hits: [String]
-
- init(hits: [String]) {
- self.hits = hits
- }
-
- func numberOfHits() -> Int {
- return hits.count
- }
+class TableViewHitsControllerTests: XCTestCase {
- func hit(atIndex index: Int) -> String? {
- return hits[index]
+ func testMissingDataSource() {
+
+ let tableView = UITableView()
+
+ let dataSource = HitsTableViewDataSource { (_, hit, _) -> UITableViewCell in
+ let cell = UITableViewCell()
+ cell.textLabel?.text = hit
+ return cell
+ }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ _ = dataSource.tableView(tableView, cellForRowAt: .init())
+ }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ _ = dataSource.tableView(tableView, numberOfRowsInSection: .init())
+ }
+
+ let delegate = HitsTableViewDelegate { _,_,_ in }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ _ = delegate.tableView(tableView, didSelectRowAt: .init())
+ }
+
}
-}
+ func testTemplate() {
+
+ let tableView = UITableView()
+
+ let hitsDataSource = TestHitsSource(hits: ["t1", "t2", "t3"])
+
+ let dataSource = HitsTableViewDataSource { (_, hit, _) -> UITableViewCell in
+ let cell = UITableViewCell()
+ cell.textLabel?.text = hit
+ return cell
+ }
+
+ dataSource.hitsSource = hitsDataSource
+
+ dataSource.templateCellProvider = { return TestTemplateCell() }
-class TableViewHitsControllerTests: XCTestCase {
+ XCTAssert(dataSource.tableView(tableView, cellForRowAt: IndexPath(row: 4, section: 0)) is TestTemplateCell, "")
+
+ }
func testDataSource() {
diff --git a/Tests/TableViewMultiIndexHitsControllerTests.swift b/Tests/TableViewMultiIndexHitsControllerTests.swift
index 9ab3aabe..8d1f61b9 100644
--- a/Tests/TableViewMultiIndexHitsControllerTests.swift
+++ b/Tests/TableViewMultiIndexHitsControllerTests.swift
@@ -10,28 +10,6 @@ import InstantSearchCore
import Foundation
import XCTest
-class TestMultiHitsDataSource: MultiIndexHitsSource {
-
- let hitsBySection: [[String]]
-
- init(hitsBySection: [[String]]) {
- self.hitsBySection = hitsBySection
- }
-
- func numberOfSections() -> Int {
- return hitsBySection.count
- }
-
- func numberOfHits(inSection section: Int) -> Int {
- return hitsBySection[section].count
- }
-
- func hit(atIndex index: Int, inSection section: Int) throws -> R? {
- return hitsBySection[section][index] as? R
- }
-
-}
-
class TableViewMultiIndexHitsControllerTests: XCTestCase {
func testDataSource() {
@@ -64,8 +42,72 @@ class TableViewMultiIndexHitsControllerTests: XCTestCase {
}
- func testWidget() {
+ func testMissingHitsSource() {
+
+ let tableView = UITableView()
+ let dataSource = MultiIndexHitsTableViewDataSource()
+
+ dataSource.setCellConfigurator(forSection: 0) { (_, h: String, _) -> UITableViewCell in
+ let cell = UITableViewCell()
+ cell.textLabel?.text = h
+ return cell
+ }
+
+ let delegate = MultiIndexHitsTableViewDelegate()
+
+ delegate.setClickHandler(forSection: 0) { (_, h: String, _) in
+ }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ _ = dataSource.numberOfSections(in: tableView)
+ }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ _ = dataSource.tableView(tableView, numberOfRowsInSection: 0)
+ }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ _ = dataSource.tableView(tableView, cellForRowAt: IndexPath(item: 0, section: 0))
+ }
+
+ expectFatalError(expectedMessage: "Missing hits source") {
+ delegate.tableView(tableView, didSelectRowAt: IndexPath(item: 0, section: 0))
+ }
+
+ }
+
+
+ func testMissingCellHandler() {
+
+ let tableView = UITableView()
+
+ let dataSource = MultiIndexHitsTableViewDataSource()
+
+ let hitsSource = TestMultiHitsDataSource(hitsBySection: [["t11", "t12"], ["t21", "t22", "t23"]])
+
+ dataSource.hitsSource = hitsSource
+
+ expectFatalError(expectedMessage: "No cell configurator found for section 0") {
+ _ = dataSource.tableView(tableView, cellForRowAt: IndexPath(item: 0, section: 0))
+ }
+
+ }
+
+ func testMissingClickHandler() {
+
+ let tableView = UITableView()
+
+ let delegate = MultiIndexHitsTableViewDelegate()
+
+ let hitsSource = TestMultiHitsDataSource(hitsBySection: [["t11", "t12"], ["t21", "t22", "t23"]])
+
+ delegate.hitsSource = hitsSource
+
+ expectFatalError(expectedMessage: "No click handler found for section 0") {
+ _ = delegate.tableView(tableView, didSelectRowAt: IndexPath(row: 0, section: 0))
+ }
+
}
}
diff --git a/Tests/TestHitsSource.swift b/Tests/TestHitsSource.swift
new file mode 100644
index 00000000..08ca33b7
--- /dev/null
+++ b/Tests/TestHitsSource.swift
@@ -0,0 +1,30 @@
+//
+// TestHitsSource.swift
+// InstantSearchTests
+//
+// Created by Vladislav Fitc on 04/09/2019.
+//
+
+@testable import InstantSearch
+import Foundation
+
+class TestHitsSource: HitsSource {
+
+ typealias Hit = String
+
+ let hits: [String]
+
+ init(hits: [String]) {
+ self.hits = hits
+ }
+
+ func numberOfHits() -> Int {
+ return hits.count
+ }
+
+ func hit(atIndex index: Int) -> String? {
+ guard index < hits.count else { return nil }
+ return hits[index]
+ }
+
+}
diff --git a/Tests/TestMultiHitsDataSource.swift b/Tests/TestMultiHitsDataSource.swift
new file mode 100644
index 00000000..e7815396
--- /dev/null
+++ b/Tests/TestMultiHitsDataSource.swift
@@ -0,0 +1,31 @@
+//
+// TestMultiHitsDataSource.swift
+// InstantSearchTests
+//
+// Created by Vladislav Fitc on 04/09/2019.
+//
+
+@testable import InstantSearch
+import Foundation
+
+class TestMultiHitsDataSource: MultiIndexHitsSource {
+
+ let hitsBySection: [[String]]
+
+ init(hitsBySection: [[String]]) {
+ self.hitsBySection = hitsBySection
+ }
+
+ func numberOfSections() -> Int {
+ return hitsBySection.count
+ }
+
+ func numberOfHits(inSection section: Int) -> Int {
+ return hitsBySection[section].count
+ }
+
+ func hit(atIndex index: Int, inSection section: Int) throws -> R? {
+ return hitsBySection[section][index] as? R
+ }
+
+}
diff --git a/instantsearch.xcodeproj/project.pbxproj b/instantsearch.xcodeproj/project.pbxproj
index 2f10c31f..5082f180 100644
--- a/instantsearch.xcodeproj/project.pbxproj
+++ b/instantsearch.xcodeproj/project.pbxproj
@@ -23,6 +23,12 @@
AF3DE598224AA00400C8BC08 /* MultiIndexHitsCollectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF3DE596224AA00400C8BC08 /* MultiIndexHitsCollectionController.swift */; };
AF3DE5BD224BBF7000C8BC08 /* TableViewHitsControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF3DE5A9224BBE6700C8BC08 /* TableViewHitsControllerTests.swift */; };
AF3DE5BE224BBF7000C8BC08 /* TableViewMultiIndexHitsControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF3DE5B1224BBEC000C8BC08 /* TableViewMultiIndexHitsControllerTests.swift */; };
+ AF58089123200CCA00C5BDFA /* FatalErrorUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF58089023200CCA00C5BDFA /* FatalErrorUtil.swift */; };
+ AF58089423200D0200C5BDFA /* FatalErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF58089223200CFE00C5BDFA /* FatalErrorTest.swift */; };
+ AF5808982320158700C5BDFA /* TestMultiHitsDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF5808972320158700C5BDFA /* TestMultiHitsDataSource.swift */; };
+ AF58089A232016E300C5BDFA /* CollectionViewMultiIndexHitsControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF5808952320155500C5BDFA /* CollectionViewMultiIndexHitsControllerTests.swift */; };
+ AF58089C2320170900C5BDFA /* TestHitsSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF58089B2320170900C5BDFA /* TestHitsSource.swift */; };
+ AF58089E2320172A00C5BDFA /* CollectionViewHitsControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF58089D2320172A00C5BDFA /* CollectionViewHitsControllerTests.swift */; };
AF5D103022F45EB300DE13AA /* FacetListTableController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF5D102F22F45EB300DE13AA /* FacetListTableController.swift */; };
AF6778B522FB235600850ACC /* SegmentedController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF6778B422FB235600850ACC /* SegmentedController.swift */; };
AF67793C2301B9C000850ACC /* FilterListTableController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF67793B2301B9C000850ACC /* FilterListTableController.swift */; };
@@ -84,6 +90,12 @@
AF3DE596224AA00400C8BC08 /* MultiIndexHitsCollectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiIndexHitsCollectionController.swift; sourceTree = ""; };
AF3DE5A9224BBE6700C8BC08 /* TableViewHitsControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewHitsControllerTests.swift; sourceTree = ""; };
AF3DE5B1224BBEC000C8BC08 /* TableViewMultiIndexHitsControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewMultiIndexHitsControllerTests.swift; sourceTree = ""; };
+ AF58089023200CCA00C5BDFA /* FatalErrorUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FatalErrorUtil.swift; sourceTree = ""; };
+ AF58089223200CFE00C5BDFA /* FatalErrorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FatalErrorTest.swift; sourceTree = ""; };
+ AF5808952320155500C5BDFA /* CollectionViewMultiIndexHitsControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewMultiIndexHitsControllerTests.swift; sourceTree = ""; };
+ AF5808972320158700C5BDFA /* TestMultiHitsDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestMultiHitsDataSource.swift; sourceTree = ""; };
+ AF58089B2320170900C5BDFA /* TestHitsSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHitsSource.swift; sourceTree = ""; };
+ AF58089D2320172A00C5BDFA /* CollectionViewHitsControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewHitsControllerTests.swift; sourceTree = ""; };
AF5D102F22F45EB300DE13AA /* FacetListTableController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FacetListTableController.swift; sourceTree = ""; };
AF6778B422FB235600850ACC /* SegmentedController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedController.swift; sourceTree = ""; };
AF67793B2301B9C000850ACC /* FilterListTableController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FilterListTableController.swift; path = Sources/Controller/FilterList/FilterListTableController.swift; sourceTree = SOURCE_ROOT; };
@@ -168,8 +180,13 @@
children = (
E25FB0A21ECF550C006B8CED /* Info.plist */,
E2A477021EC62031007CA367 /* InstantSearch-Tests-Bridging-Header.h */,
+ AF58089B2320170900C5BDFA /* TestHitsSource.swift */,
AF3DE5A9224BBE6700C8BC08 /* TableViewHitsControllerTests.swift */,
+ AF58089D2320172A00C5BDFA /* CollectionViewHitsControllerTests.swift */,
+ AF5808972320158700C5BDFA /* TestMultiHitsDataSource.swift */,
AF3DE5B1224BBEC000C8BC08 /* TableViewMultiIndexHitsControllerTests.swift */,
+ AF5808952320155500C5BDFA /* CollectionViewMultiIndexHitsControllerTests.swift */,
+ AF58089223200CFE00C5BDFA /* FatalErrorTest.swift */,
);
path = Tests;
sourceTree = "";
@@ -177,6 +194,7 @@
28F828971C494B4200330CF4 /* Sources */ = {
isa = PBXGroup;
children = (
+ AF58089023200CCA00C5BDFA /* FatalErrorUtil.swift */,
AF6C6F7A2253C5A1001E5E3C /* Controller */,
28F828821C494B2C00330CF4 /* Info.plist */,
E2A477001EC61B43007CA367 /* InstantSearch-Bridging-Header.h */,
@@ -473,6 +491,7 @@
};
28F828861C494B2C00330CF4 = {
CreatedOnToolsVersion = 7.2;
+ DevelopmentTeam = JF98Q6D3JZ;
LastSwiftMigration = 0900;
TestTargetID = E27B67E01ED339290001FFA7;
};
@@ -574,6 +593,7 @@
AF3DE594224A9B7A00C8BC08 /* MultiIndexHitsTableController.swift in Sources */,
AF9396812298140D00757257 /* ActivityIndicatorController.swift in Sources */,
AF67793C2301B9C000850ACC /* FilterListTableController.swift in Sources */,
+ AF58089123200CCA00C5BDFA /* FatalErrorUtil.swift in Sources */,
E2EFA5F022AEB980008C9CAA /* NumericStepperController.swift in Sources */,
AF3DE597224AA00400C8BC08 /* HitsCollectionController.swift in Sources */,
AF14E31022F43C710088D2A7 /* MultiIndexHitsTableViewDelegate.swift in Sources */,
@@ -605,7 +625,12 @@
buildActionMask = 2147483647;
files = (
AF3DE5BD224BBF7000C8BC08 /* TableViewHitsControllerTests.swift in Sources */,
+ AF58089423200D0200C5BDFA /* FatalErrorTest.swift in Sources */,
+ AF58089C2320170900C5BDFA /* TestHitsSource.swift in Sources */,
+ AF5808982320158700C5BDFA /* TestMultiHitsDataSource.swift in Sources */,
+ AF58089A232016E300C5BDFA /* CollectionViewMultiIndexHitsControllerTests.swift in Sources */,
AF3DE5BE224BBF7000C8BC08 /* TableViewMultiIndexHitsControllerTests.swift in Sources */,
+ AF58089E2320172A00C5BDFA /* CollectionViewHitsControllerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -839,6 +864,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ENABLE_MODULES = YES;
+ DEVELOPMENT_TEAM = JF98Q6D3JZ;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
@@ -860,6 +886,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ENABLE_MODULES = YES;
+ DEVELOPMENT_TEAM = JF98Q6D3JZ;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",