diff --git a/ColorPicker/ColorPickerRow.swift b/ColorPicker/ColorPickerRow.swift index 35ab02a..4bac071 100644 --- a/ColorPicker/ColorPickerRow.swift +++ b/ColorPicker/ColorPickerRow.swift @@ -238,7 +238,7 @@ public final class ColorPickerCell : Cell, CellType, UICollectionViewDe // MARK: MyCustomRow -open class _ColorPickerRow: Row { +public class _ColorPickerRow: Row { open var showsCurrentSwatch = true { didSet { diff --git a/ColorPicker/ColorRow.swift b/ColorPicker/ColorRow.swift index 216d4b3..091d94e 100644 --- a/ColorPicker/ColorRow.swift +++ b/ColorPicker/ColorRow.swift @@ -49,7 +49,7 @@ public final class ColorCell : Cell, CellType { // MARK: MyCustomRow -open class _ColorRow: Row { +public class _ColorRow: Row { var isCircular = false { didSet { diff --git a/ColorPickerRow.podspec b/ColorPickerRow.podspec index 780d044..ea02cc4 100644 --- a/ColorPickerRow.podspec +++ b/ColorPickerRow.podspec @@ -1,17 +1,17 @@ Pod::Spec.new do |s| s.name = 'ColorPickerRow' - s.version = '0.1.0' + s.version = '1.1.0' s.license = 'MIT' s.summary = 'A color picker row for use with the Eureka form library' s.homepage = 'https://github.com/EurekaCommunity/ColorPickerRow' - s.source = { :git => 'https://github.com/EurekaCommunity/ColorPickerRow.git'} + s.source = { :git => 'https://github.com/EurekaCommunity/ColorPickerRow.git' } s.ios.deployment_target = '8.0' s.ios.frameworks = 'UIKit', 'Foundation' s.source_files = 'ColorPicker/**/*.swift' s.requires_arc = true s.author = "Mark Alldritt" s.dependencies = { - 'Eureka' => '> 2.0.0', - 'UIColor_Hex_Swift' => '~> 3.0.2' + 'Eureka' => '>= 4.0.0', + 'UIColor_Hex_Swift' } end \ No newline at end of file diff --git a/Example.xcodeproj/project.pbxproj b/Example.xcodeproj/project.pbxproj index c99a6e7..7c971e9 100644 --- a/Example.xcodeproj/project.pbxproj +++ b/Example.xcodeproj/project.pbxproj @@ -193,9 +193,14 @@ files = ( ); inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-ColorPicker/Pods-ColorPicker-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/Eureka/Eureka.framework", + "${BUILT_PRODUCTS_DIR}/UIColor_Hex_Swift/UIColor_Hex_Swift.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Eureka.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/UIColor_Hex_Swift.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -223,13 +228,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-ColorPicker-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -379,7 +387,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.latenightsw.EurekaCustomView; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -396,7 +404,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.latenightsw.EurekaCustomView; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Release; }; diff --git a/Podfile b/Podfile index baeb360..c5062db 100644 --- a/Podfile +++ b/Podfile @@ -1,10 +1,10 @@ platform :ios, '10.0' source 'https://github.com/CocoaPods/Specs.git' -target ‘ColorPicker’ do +target 'ColorPicker' do use_frameworks! - pod 'Eureka', :git => 'https://github.com/xmartlabs/Eureka.git', :branch => 'master' #'~> 2.0.0-beta.1' - pod 'UIColor_Hex_Swift', '~> 3.0.2' + pod 'Eureka', '>= 4.0.0' + pod 'UIColor_Hex_Swift' end diff --git a/Podfile.lock b/Podfile.lock index aea47bd..3a19d58 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,25 +1,15 @@ PODS: - - Eureka (3.0.0) + - Eureka (4.0.0) - UIColor_Hex_Swift (3.0.2) DEPENDENCIES: - - Eureka (from `https://github.com/xmartlabs/Eureka.git`, branch `master`) - - UIColor_Hex_Swift (~> 3.0.2) - -EXTERNAL SOURCES: - Eureka: - :branch: master - :git: https://github.com/xmartlabs/Eureka.git - -CHECKOUT OPTIONS: - Eureka: - :commit: 77cb04f587a4e83f28ad5f3174f6f8f6c086b524 - :git: https://github.com/xmartlabs/Eureka.git + - Eureka (~> 4.0.0) + - UIColor_Hex_Swift SPEC CHECKSUMS: - Eureka: 5b9418d7bfdc21ca977d69d124a6409f3e9af2c7 + Eureka: c0b55d2aec82050c1400c7d65960b700be8d10ef UIColor_Hex_Swift: 95f718452092a3efc8a827dffd2c04d3237be02d -PODFILE CHECKSUM: af7f6296626bb44cb5f6bedfacf378f45aa2c098 +PODFILE CHECKSUM: 309386d4cd991af5cee3f3de160a3338b893ff73 -COCOAPODS: 1.2.1 +COCOAPODS: 1.3.1 diff --git a/Pods/Eureka/README.md b/Pods/Eureka/README.md index 25a0603..3c8dc4c 100644 --- a/Pods/Eureka/README.md +++ b/Pods/Eureka/README.md @@ -3,7 +3,7 @@

Build status Platform iOS -Swift 3 compatible +Swift 4 compatible Carthage compatible CocoaPods compatible License: MIT @@ -53,9 +53,8 @@ Made with ❤️ by [XMARTLABS](http://xmartlabs.com). This is the re-creation o ## Requirements -* iOS 8.0+ -* Xcode 8+ -* Swift 3 +* Xcode 9+ +* Swift 4 ### Example project @@ -324,7 +323,7 @@ Section(){ section in In this case we are hiding and showing whole sections. -To accomplish this each row has an `hidden` variable of optional type `Condition` which can be set using a function or `NSPredicate`. +To accomplish this each row has a `hidden` variable of optional type `Condition` which can be set using a function or `NSPredicate`. #### Hiding using a function condition @@ -475,19 +474,19 @@ form +++ Previous code snippet shows how to create a multivalued section. In this case we want to insert, delete and reorder rows as multivaluedOptions argument indicates. -`addButtonProvider` allows us to customize the button row which inserts a new row when tapped and `multivaluedOptions` contains .Insert` value. +`addButtonProvider` allows us to customize the button row which inserts a new row when tapped and `multivaluedOptions` contains `.Insert` value. `multivaluedRowToInsertAt` closure property is called by Eureka each time a new row needs to be inserted. In order to provide the row to add into multivalued section we should set this property. Eureka passes the index as closure parameter. Notice that we can return any kind of row, even custom rows, even though in most cases multivalued section rows are of the same type. Eureka automatically adds a button row when we create a insertable multivalued section. We can customize how the this button row looks like as we explained before. `showInsertIconInAddButton` property indicates if plus button (insert style) should appear in the left of the button, true by default. -There are some considerations we need to have in mind when creating insertable sections. Any row added to the insertable multivalued section should be placed above the row that Eureka automatically adds to insert new rows. This can be easily achieved by adding these additional rows to the section from inside section's initializer closure (last parameter of section initializer) so then Eureka adds the adds insert button at the end of the section. +There are some considerations we need to have in mind when creating insertable sections. Any row added to the insertable multivalued section should be placed above the row that Eureka automatically adds to insert new rows. This can be easily achieved by adding these additional rows to the section from inside the section's initializer closure (last parameter of section initializer) so then Eureka adds the adds insert button at the end of the section. For more information on how to use multivalued sections please take a look at Eureka example project which contains several usage examples. ### Validations -Eureka 2.0.0 introduces the very requested build-in validations feature. +Eureka 2.0.0 introduces the much requested built-in validations feature. A row has a collection of `Rules` and a specific configuration that determines when validation rules should be evaluated. @@ -578,6 +577,10 @@ If you want to validate the entire form (all the rows) you can manually invoke F Each row has the `validationErrors` property that can be used to retrieve all validation errors. This property just holds the validation error list of the latest row validation execution, which means it doesn't evaluate the validation rules of the row. +#### Note on types + +As expected, the Rules must use the same types as the Row object. Be extra careful to check the row type used. You might see a compiler error ("Incorrect arugment label in call (have 'rule:' expected 'ruleSet:')" that is not pointing to the problem when mixing types. + ## Custom rows It is very common that you need a row that is different from those included in Eureka. If this is the case you will have to create your own row but this should not be difficult. You can read [this tutorial on how to create custom rows](https://blog.xmartlabs.com/2016/09/06/Eureka-custom-row-tutorial/) to get started. You might also want to have a look at [EurekaCommunity] which includes some extra rows ready to be added to Eureka. @@ -661,7 +664,7 @@ public override func customDidSelect() { To create a custom Presenter row you must create a class that conforms the `PresenterRowType` protocol. It is highly recommended to subclass `SelectorRow` as it does conform to that protocol and adds other useful functionality. -The PresenterRowType protocol is defined as followes: +The PresenterRowType protocol is defined as follows: ```swift public protocol PresenterRowType: TypedRowType { typealias ProviderType : UIViewController, TypedRowControllerType @@ -670,7 +673,7 @@ public protocol PresenterRowType: TypedRowType { } ``` -The onPresentCallback will be called when the row is about to present another view controller. This is done in the `SelectorRow` so if you do not sublass it you will have to call it yourself. +The onPresentCallback will be called when the row is about to present another view controller. This is done in the `SelectorRow` so if you do not subclass it you will have to call it yourself. The `presentationMode` is what defines how the controller is presented and which controller is presented. This presentation can be using a Segue identifier, a segue class, presenting a controller modally or pushing to a specific view controller. For example a CustomPushRow can be defined like this: @@ -926,7 +929,7 @@ $ pod install Specify Eureka into your project's `Cartfile`: ```ogdl -github "xmartlabs/Eureka" ~> 3.0 +github "xmartlabs/Eureka" ~> 4.0 ``` #### Manually as Embedded Framework diff --git a/Pods/Eureka/Source/Core/BaseRow.swift b/Pods/Eureka/Source/Core/BaseRow.swift index b2482f0..747a805 100644 --- a/Pods/Eureka/Source/Core/BaseRow.swift +++ b/Pods/Eureka/Source/Core/BaseRow.swift @@ -35,6 +35,8 @@ open class BaseRow: BaseRowType { var callbackOnCellHighlightChanged: (() -> Void)? var callbackOnRowValidationChanged: (() -> Void)? var _inlineRow: BaseRow? + + var _cachedOptionsData: Any? public var validationOptions: ValidationOptions = .validatesOnBlur // validation state @@ -212,6 +214,11 @@ extension BaseRow { removeFromRowObservers() } + final func willBeRemovedFromSection() { + willBeRemovedFromForm() + section = nil + } + final func removeFromHiddenRowObservers() { guard let h = hidden else { return } switch h { diff --git a/Pods/Eureka/Source/Core/Cell.swift b/Pods/Eureka/Source/Core/Cell.swift index 3d11b67..0454878 100644 --- a/Pods/Eureka/Source/Core/Cell.swift +++ b/Pods/Eureka/Source/Core/Cell.swift @@ -85,7 +85,7 @@ open class BaseCell: UITableViewCell, BaseCellType { } /// Generic class that represents the Eureka cells. -open class Cell : BaseCell, TypedCellType { +open class Cell: BaseCell, TypedCellType where T: Equatable { public typealias Value = T @@ -106,7 +106,6 @@ open class Cell : BaseCell, TypedCellType { required public init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) - height = { UITableViewAutomaticDimension } } /** diff --git a/Pods/Eureka/Source/Core/Core.swift b/Pods/Eureka/Source/Core/Core.swift index 618b305..b6d3f86 100644 --- a/Pods/Eureka/Source/Core/Core.swift +++ b/Pods/Eureka/Source/Core/Core.swift @@ -109,18 +109,6 @@ public enum ControllerProvider { } } -/** - * Responsible for the options passed to a selector view controller - */ -public struct DataProvider { - - public let arrayData: [T]? - - public init(arrayData: [T]) { - self.arrayData = arrayData - } -} - /** Defines how a controller should be presented. @@ -325,8 +313,8 @@ public enum EurekaError: Error { public protocol FormViewControllerProtocol { var tableView: UITableView! { get } - func beginEditing(of: Cell) - func endEditing(of: Cell) + func beginEditing(of: Cell) + func endEditing(of: Cell) func insertAnimation(forRows rows: [BaseRow]) -> UITableViewRowAnimation func deleteAnimation(forRows rows: [BaseRow]) -> UITableViewRowAnimation @@ -402,7 +390,7 @@ public struct InlineRowHideOptions: OptionSet { } /// View controller that shows a form. -open class FormViewController: UIViewController, FormViewControllerProtocol { +open class FormViewController: UIViewController, FormViewControllerProtocol, FormDelegate { @IBOutlet public var tableView: UITableView! @@ -516,8 +504,8 @@ open class FormViewController: UIViewController, FormViewControllerProtocol { NotificationCenter.default.addObserver(self, selector: #selector(FormViewController.keyboardWillHide(_:)), name: Notification.Name.UIKeyboardWillHide, object: nil) } - open override func viewDidDisappear(_ animated: Bool) { - super.viewDidDisappear(animated) + open override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardWillHide, object: nil) } @@ -551,7 +539,7 @@ open class FormViewController: UIViewController, FormViewControllerProtocol { /** Called when a cell becomes first responder */ - public final func beginEditing(of cell: Cell) { + public final func beginEditing(of cell: Cell) { cell.row.isHighlighted = true cell.row.updateCell() RowDefaults.onCellHighlightChanged["\(type(of: cell.row!))"]?(cell, cell.row) @@ -569,7 +557,7 @@ open class FormViewController: UIViewController, FormViewControllerProtocol { /** Called when a cell resigns first responder */ - public final func endEditing(of cell: Cell) { + public final func endEditing(of cell: Cell) { cell.row.isHighlighted = false cell.row.wasBlurred = true RowDefaults.onCellHighlightChanged["\(type(of: self))"]?(cell, cell.row) @@ -685,6 +673,50 @@ open class FormViewController: UIViewController, FormViewControllerProtocol { inlineRow.collapseInlineRow() } } + + // MARK: FormDelegate + + open func sectionsHaveBeenAdded(_ sections: [Section], at indexes: IndexSet) { + guard animateTableView else { return } + tableView?.beginUpdates() + tableView?.insertSections(indexes, with: insertAnimation(forSections: sections)) + tableView?.endUpdates() + } + + open func sectionsHaveBeenRemoved(_ sections: [Section], at indexes: IndexSet) { + guard animateTableView else { return } + tableView?.beginUpdates() + tableView?.deleteSections(indexes, with: deleteAnimation(forSections: sections)) + tableView?.endUpdates() + } + + open func sectionsHaveBeenReplaced(oldSections: [Section], newSections: [Section], at indexes: IndexSet) { + guard animateTableView else { return } + tableView?.beginUpdates() + tableView?.reloadSections(indexes, with: reloadAnimation(oldSections: oldSections, newSections: newSections)) + tableView?.endUpdates() + } + + open func rowsHaveBeenAdded(_ rows: [BaseRow], at indexes: [IndexPath]) { + guard animateTableView else { return } + tableView?.beginUpdates() + tableView?.insertRows(at: indexes, with: insertAnimation(forRows: rows)) + tableView?.endUpdates() + } + + open func rowsHaveBeenRemoved(_ rows: [BaseRow], at indexes: [IndexPath]) { + guard animateTableView else { return } + tableView?.beginUpdates() + tableView?.deleteRows(at: indexes, with: deleteAnimation(forRows: rows)) + tableView?.endUpdates() + } + + open func rowsHaveBeenReplaced(oldRows: [BaseRow], newRows: [BaseRow], at indexes: [IndexPath]) { + guard animateTableView else { return } + tableView?.beginUpdates() + tableView?.reloadRows(at: indexes, with: reloadAnimation(oldRows: oldRows, newRows: newRows)) + tableView?.endUpdates() + } // MARK: Private @@ -769,10 +801,10 @@ extension FormViewController : UITableViewDelegate { return true } - public func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { + open func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { let row = form[indexPath] - var section = row.section! + let section = row.section! if let _ = row.baseCell.findFirstResponder() { tableView.endEditing(true) } @@ -801,7 +833,7 @@ extension FormViewController : UITableViewDelegate { } } - public func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { + open func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { guard let section = form[indexPath.section] as? MultivaluedSection, section.multivaluedOptions.contains(.Reorder) && section.count > 1 else { return false } @@ -814,7 +846,7 @@ extension FormViewController : UITableViewDelegate { return true } - public func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath { + open func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath { guard let section = form[sourceIndexPath.section] as? MultivaluedSection else { return sourceIndexPath } guard sourceIndexPath.section == proposedDestinationIndexPath.section else { return sourceIndexPath } @@ -835,7 +867,7 @@ extension FormViewController : UITableViewDelegate { return proposedDestinationIndexPath } - public func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { + open func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { guard var section = form[sourceIndexPath.section] as? MultivaluedSection else { return } if sourceIndexPath.row < section.count && destinationIndexPath.row < section.count && sourceIndexPath.row != destinationIndexPath.row { @@ -850,7 +882,7 @@ extension FormViewController : UITableViewDelegate { } } - public func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle { + open func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle { guard let section = form[indexPath.section] as? MultivaluedSection else { return .none } @@ -863,7 +895,7 @@ extension FormViewController : UITableViewDelegate { return .none } - public func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool { + open func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool { return self.tableView(tableView, editingStyleForRowAt: indexPath) != .none } } @@ -894,52 +926,6 @@ extension FormViewController : UITableViewDataSource { } } -extension FormViewController: FormDelegate { - - // MARK: FormDelegate - - open func sectionsHaveBeenAdded(_ sections: [Section], at indexes: IndexSet) { - guard animateTableView else { return } - tableView?.beginUpdates() - tableView?.insertSections(indexes, with: insertAnimation(forSections: sections)) - tableView?.endUpdates() - } - - open func sectionsHaveBeenRemoved(_ sections: [Section], at indexes: IndexSet) { - guard animateTableView else { return } - tableView?.beginUpdates() - tableView?.deleteSections(indexes, with: deleteAnimation(forSections: sections)) - tableView?.endUpdates() - } - - open func sectionsHaveBeenReplaced(oldSections: [Section], newSections: [Section], at indexes: IndexSet) { - guard animateTableView else { return } - tableView?.beginUpdates() - tableView?.reloadSections(indexes, with: reloadAnimation(oldSections: oldSections, newSections: newSections)) - tableView?.endUpdates() - } - - open func rowsHaveBeenAdded(_ rows: [BaseRow], at indexes: [IndexPath]) { - guard animateTableView else { return } - tableView?.beginUpdates() - tableView?.insertRows(at: indexes, with: insertAnimation(forRows: rows)) - tableView?.endUpdates() - } - - open func rowsHaveBeenRemoved(_ rows: [BaseRow], at indexes: [IndexPath]) { - guard animateTableView else { return } - tableView?.beginUpdates() - tableView?.deleteRows(at: indexes, with: deleteAnimation(forRows: rows)) - tableView?.endUpdates() - } - - open func rowsHaveBeenReplaced(oldRows: [BaseRow], newRows: [BaseRow], at indexes: [IndexPath]) { - guard animateTableView else { return } - tableView?.beginUpdates() - tableView?.reloadRows(at: indexes, with: reloadAnimation(oldRows: oldRows, newRows: newRows)) - tableView?.endUpdates() - } -} extension FormViewController : UIScrollViewDelegate { @@ -958,7 +944,7 @@ extension FormViewController { /** Called when the keyboard will appear. Adjusts insets of the tableView and scrolls it if necessary. */ - open func keyboardWillShow(_ notification: Notification) { + @objc open func keyboardWillShow(_ notification: Notification) { guard let table = tableView, let cell = table.findFirstResponder()?.formCell() else { return } let keyBoardInfo = notification.userInfo! let endFrame = keyBoardInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue @@ -986,7 +972,7 @@ extension FormViewController { /** Called when the keyboard will disappear. Adjusts insets of the tableView. */ - open func keyboardWillHide(_ notification: Notification) { + @objc open func keyboardWillHide(_ notification: Notification) { guard let table = tableView, let oldBottom = oldBottomInset else { return } let keyBoardInfo = notification.userInfo! var tableInsets = table.contentInset @@ -1009,11 +995,11 @@ extension FormViewController { // MARK: Navigation Methods - func navigationDone(_ sender: UIBarButtonItem) { + @objc func navigationDone(_ sender: UIBarButtonItem) { tableView?.endEditing(true) } - func navigationAction(_ sender: UIBarButtonItem) { + @objc func navigationAction(_ sender: UIBarButtonItem) { navigateTo(direction: sender == navigationAccessoryView.previousButton ? .up : .down) } diff --git a/Pods/Eureka/Source/Core/Form.swift b/Pods/Eureka/Source/Core/Form.swift index 61379b3..d788695 100644 --- a/Pods/Eureka/Source/Core/Form.swift +++ b/Pods/Eureka/Source/Core/Form.swift @@ -70,7 +70,7 @@ public final class Form { /** Returns the row whose tag is passed as parameter. Uses a dictionary to get the row faster */ - public func rowBy(tag: String) -> RowOf? { + public func rowBy(tag: String) -> RowOf? where T: Equatable{ let row: BaseRow? = rowBy(tag: tag) return row as? RowOf } @@ -78,7 +78,7 @@ public final class Form { /** Returns the row whose tag is passed as parameter. Uses a dictionary to get the row faster */ - public func rowBy(tag: String) -> Row? { + public func rowBy(tag: String) -> Row? where Row: RowType{ let row: BaseRow? = rowBy(tag: tag) return row as? Row } @@ -106,19 +106,11 @@ public final class Form { */ public func values(includeHidden: Bool = false) -> [String: Any?] { if includeHidden { - return allRows.filter({ $0.tag != nil }) - .reduce([String: Any?]()) { - var result = $0 - result[$1.tag!] = $1.baseValue - return result - } + return getValues(for: allRows.filter({ $0.tag != nil })) + .merging(getValues(for: allSections.filter({ $0 is MultivaluedSection && $0.tag != nil }) as? [MultivaluedSection]), uniquingKeysWith: {(_, new) in new }) } - return rows.filter({ $0.tag != nil }) - .reduce([String: Any?]()) { - var result = $0 - result[$1.tag!] = $1.baseValue - return result - } + return getValues(for: rows.filter({ $0.tag != nil })) + .merging(getValues(for: allSections.filter({ $0 is MultivaluedSection && $0.tag != nil }) as? [MultivaluedSection]), uniquingKeysWith: {(_, new) in new }) } /** @@ -172,7 +164,24 @@ extension Form: MutableCollection { public subscript (_ position: Int) -> Section { get { return kvoWrapper.sections[position] as! Section } - set { kvoWrapper.sections[position] = newValue } + set { + if position > kvoWrapper.sections.count { + assertionFailure("Form: Index out of bounds") + } + + if position < kvoWrapper.sections.count { + let oldSection = kvoWrapper.sections[position] + let oldSectionIndex = kvoWrapper._allSections.index(of: oldSection as! Section)! + // Remove the previous section from the form + kvoWrapper._allSections[oldSectionIndex].willBeRemovedFromForm() + kvoWrapper._allSections[oldSectionIndex] = newValue + } else { + kvoWrapper._allSections.append(newValue) + } + + kvoWrapper.sections[position] = newValue + newValue.wasAddedTo(form: self) + } } public func index(after i: Int) -> Int { return i+1 <= endIndex ? i+1 : endIndex @@ -246,7 +255,7 @@ extension Form { // MARK: Private Helpers class KVOWrapper: NSObject { - dynamic private var _sections = NSMutableArray() + @objc dynamic private var _sections = NSMutableArray() var sections: NSMutableArray { return mutableArrayValue(forKey: "_sections") } var _allSections = [Section]() private weak var form: Form? @@ -343,6 +352,22 @@ extension Form { } kvoWrapper.sections.insert(section, at: formIndex == NSNotFound ? 0 : formIndex + 1 ) } + + func getValues(for rows: [BaseRow]) -> [String: Any?] { + return rows.reduce([String: Any?]()) { + var result = $0 + result[$1.tag!] = $1.baseValue + return result + } + } + + func getValues(for multivaluedSections: [MultivaluedSection]?) -> [String: [Any?]] { + return multivaluedSections?.reduce([String: [Any?]]()) { + var result = $0 + result[$1.tag!] = $1.values() + return result + } ?? [:] + } } extension Form { diff --git a/Pods/Eureka/Source/Core/Helpers.swift b/Pods/Eureka/Source/Core/Helpers.swift index b5bd153..0a8dc11 100644 --- a/Pods/Eureka/Source/Core/Helpers.swift +++ b/Pods/Eureka/Source/Core/Helpers.swift @@ -68,9 +68,9 @@ extension NSExpression { case .function, .variable: let str = "\(self)" if let range = str.range(of: ".") { - return [str.substring(with: str.characters.index(str.startIndex, offsetBy: 1)..? { get set } + var presentationMode: PresentationMode? { get set } /// Will be called before the presentation occurs. - var onPresentCallback: ((FormViewController, ProviderType) -> Void)? { get set } + var onPresentCallback: ((FormViewController, PresentedControllerType) -> Void)? { get set } } extension PresenterRowType { @@ -48,7 +48,7 @@ extension PresenterRowType { - returns: this row */ - public func onPresent(_ callback: ((FormViewController, ProviderType) -> Void)?) -> Self { + public func onPresent(_ callback: ((FormViewController, PresentedControllerType) -> Void)?) -> Self { onPresentCallback = callback return self } diff --git a/Pods/Eureka/Source/Core/Row.swift b/Pods/Eureka/Source/Core/Row.swift index b991e11..60c8516 100644 --- a/Pods/Eureka/Source/Core/Row.swift +++ b/Pods/Eureka/Source/Core/Row.swift @@ -24,7 +24,7 @@ import Foundation -open class RowOf: BaseRow { +open class RowOf: BaseRow where T: Equatable{ private var _value: T? { didSet { @@ -55,7 +55,7 @@ open class RowOf: BaseRow { _value = newValue guard let _ = section?.form else { return } wasChanged = true - if validationOptions.contains(.validatesOnChange) || (wasBlurred && validationOptions.contains(.validatesOnChangeAfterBlurred)) || !isValid { + if validationOptions.contains(.validatesOnChange) || (wasBlurred && validationOptions.contains(.validatesOnChangeAfterBlurred)) || (!isValid && validationOptions != .validatesOnDemand) { validate() } } @@ -70,9 +70,6 @@ open class RowOf: BaseRow { set { value = newValue as? T } } - /// Variable used in rows with options that serves to generate the options for that row. - public var dataProvider: DataProvider? - /// Block variable used to get the String that should be displayed for the value of this row. public var displayValueFor: ((T?) -> String?)? = { return $0.map { String(describing: $0) } @@ -90,6 +87,8 @@ open class RowOf: BaseRow { return validationErrors } + /// Add a Validation rule for the Row + /// - Parameter rule: RuleType object to add public func add(rule: Rule) where T == Rule.RowValueType { let validFn: ((T?) -> ValidationError?) = { (val: T?) in return rule.isValid(value: val) @@ -97,6 +96,8 @@ open class RowOf: BaseRow { rules.append(ValidationRuleHelper(validateFn: validFn, rule: rule)) } + /// Add a Validation rule set for the Row + /// - Parameter ruleSet: RuleSet set of rules to add public func add(ruleSet: RuleSet) { rules.append(contentsOf: ruleSet.rules) } diff --git a/Pods/Eureka/Source/Core/Section.swift b/Pods/Eureka/Source/Core/Section.swift index 17154a9..27395db 100644 --- a/Pods/Eureka/Source/Core/Section.swift +++ b/Pods/Eureka/Source/Core/Section.swift @@ -53,7 +53,7 @@ extension Section { internal class KVOWrapper: NSObject { - dynamic private var _rows = NSMutableArray() + @objc dynamic private var _rows = NSMutableArray() var rows: NSMutableArray { return mutableArrayValue(forKey: "_rows") } @@ -193,12 +193,13 @@ open class Section { // MARK: Private lazy var kvoWrapper: KVOWrapper = { [unowned self] in return KVOWrapper(section: self) }() + var headerView: UIView? var footerView: UIView? var hiddenCache = false } -extension Section : MutableCollection, BidirectionalCollection { +extension Section: MutableCollection, BidirectionalCollection { // MARK: MutableCollectionType @@ -211,20 +212,39 @@ extension Section : MutableCollection, BidirectionalCollection { } return kvoWrapper.rows[position] as! BaseRow } - set { kvoWrapper.rows[position] = newValue } + set { + if position > kvoWrapper.rows.count { + assertionFailure("Section: Index out of bounds") + } + + if position < kvoWrapper.rows.count { + let oldRow = kvoWrapper.rows[position] + let oldRowIndex = kvoWrapper._allRows.index(of: oldRow as! BaseRow)! + // Remove the previous row from the form + kvoWrapper._allRows[oldRowIndex].willBeRemovedFromSection() + kvoWrapper._allRows[oldRowIndex] = newValue + } else { + kvoWrapper._allRows.append(newValue) + } + + kvoWrapper.rows[position] = newValue + newValue.wasAddedTo(section: self) + } } - public subscript (range: Range) -> [BaseRow] { - get { return kvoWrapper.rows.objects(at: IndexSet(integersIn: range)) as! [BaseRow] } - set { kvoWrapper.rows.replaceObjects(in: NSRange(range), withObjectsFrom: newValue) } + public subscript (range: Range) -> ArraySlice { + get { return kvoWrapper.rows.map({ $0 as! BaseRow })[range] } + set { + replaceSubrange(range, with: newValue) + } } - public func index(after i: Int) -> Int {return i + 1} - public func index(before i: Int) -> Int {return i - 1} + public func index(after i: Int) -> Int { return i + 1 } + public func index(before i: Int) -> Int { return i - 1 } } -extension Section : RangeReplaceableCollection { +extension Section: RangeReplaceableCollection { // MARK: RangeReplaceableCollectionType @@ -242,18 +262,18 @@ extension Section : RangeReplaceableCollection { } } - public func replaceSubrange(_ subRange: Range, with newElements: C) where C.Iterator.Element == BaseRow { - for i in subRange.lowerBound..(_ subrange: Range, with newElements: C) where C : Collection, C.Element == BaseRow { + for i in subrange.lowerBound.. BaseRow { + let row = kvoWrapper.rows.object(at: position) as! BaseRow + row.willBeRemovedFromSection() + kvoWrapper.rows.removeObject(at: position) + if let index = kvoWrapper._allRows.index(of: row) { + kvoWrapper._allRows.remove(at: index) + } + + return row + } + private func indexForInsertion(at index: Int) -> Int { guard index != 0 else { return 0 } @@ -438,4 +470,13 @@ open class MultivaluedSection: Section { } self <<< addRow } + + /** + Method used to get all the values of the section. + + - returns: An Array mapping the row values. [value] + */ + public func values() -> [Any?] { + return kvoWrapper._allRows.filter({ $0.baseValue != nil }).map({ $0.baseValue }) + } } diff --git a/Pods/Eureka/Source/Core/SelectableRowType.swift b/Pods/Eureka/Source/Core/SelectableRowType.swift index b2e4351..266f285 100644 --- a/Pods/Eureka/Source/Core/SelectableRowType.swift +++ b/Pods/Eureka/Source/Core/SelectableRowType.swift @@ -27,6 +27,6 @@ import Foundation /** * Every row that shall be used in a SelectableSection must conform to this protocol. */ -public protocol SelectableRowType: TypedRowType, RowType { +public protocol SelectableRowType: RowType { var selectableValue: Cell.Value? { get set } } diff --git a/Pods/Eureka/Source/Core/SelectableSection.swift b/Pods/Eureka/Source/Core/SelectableSection.swift index 28c0041..39c0677 100644 --- a/Pods/Eureka/Source/Core/SelectableSection.swift +++ b/Pods/Eureka/Source/Core/SelectableSection.swift @@ -61,8 +61,7 @@ public protocol SelectableSectionType: Collection { func selectedRows() -> [SelectableRow] } -extension SelectableSectionType where Self: Section, Self.Iterator == IndexingIterator

, Self.Iterator.Element == BaseRow { - +extension SelectableSectionType where Self: Section { /** Returns the selected row of this section. Should be used if selectionType is SingleSelection */ @@ -74,9 +73,8 @@ extension SelectableSectionType where Self: Section, Self.Iterator == IndexingIt Returns the selected rows of this section. Should be used if selectionType is MultipleSelection */ public func selectedRows() -> [SelectableRow] { - return filter({ (row: BaseRow) -> Bool in - row is SelectableRow && row.baseValue != nil - }).map({ $0 as! SelectableRow}) + let selectedRows: [BaseRow] = self.filter { $0 is SelectableRow && $0.baseValue != nil } + return selectedRows.map { $0 as! SelectableRow } } /** @@ -86,12 +84,13 @@ extension SelectableSectionType where Self: Section, Self.Iterator == IndexingIt for row in rows { if let row = row as? SelectableRow { row.onCellSelection { [weak self] cell, row in - guard let s = self else { return } + guard let s = self, !row.isDisabled else { return } switch s.selectionType { case .multipleSelection: row.value = row.value == nil ? row.selectableValue : nil case let .singleSelection(enableDeselection): - s.filter { $0.baseValue != nil && $0 != row }.forEach { + s.forEach { + guard $0.baseValue != nil && $0 != row else { return } $0.baseValue = nil $0.updateCell() } @@ -112,7 +111,7 @@ extension SelectableSectionType where Self: Section, Self.Iterator == IndexingIt } /// A subclass of Section that serves to create a section with a list of selectable options. -open class SelectableSection : Section, SelectableSectionType where Row: BaseRow { +open class SelectableSection: Section, SelectableSectionType where Row: SelectableRowType, Row: BaseRow { public typealias SelectableRow = Row @@ -123,17 +122,20 @@ open class SelectableSection : Section, SelectableSectio public var onSelectSelectableRow: ((Row.Cell, Row) -> Void)? public override init(_ initializer: (SelectableSection) -> Void) { - super.init({ section in initializer(section as! SelectableSection) }) + super.init({ _ in }) + initializer(self) } public init(_ header: String, selectionType: SelectionType, _ initializer: (SelectableSection) -> Void = { _ in }) { self.selectionType = selectionType - super.init(header, { section in initializer(section as! SelectableSection) }) + super.init(header, { _ in }) + initializer(self) } public init(header: String, footer: String, selectionType: SelectionType, _ initializer: (SelectableSection) -> Void = { _ in }) { self.selectionType = selectionType - super.init(header: header, footer: footer, { section in initializer(section as! SelectableSection) }) + super.init(header: header, footer: footer, { _ in }) + initializer(self) } public required init() { diff --git a/Pods/Eureka/Source/Core/Validation.swift b/Pods/Eureka/Source/Core/Validation.swift index 15f4f33..0c0c442 100644 --- a/Pods/Eureka/Source/Core/Validation.swift +++ b/Pods/Eureka/Source/Core/Validation.swift @@ -64,7 +64,7 @@ public struct ValidationOptions: OptionSet { public static let validatesAlways: ValidationOptions = [.validatesOnChange, .validatesOnBlur] } -internal struct ValidationRuleHelper { +internal struct ValidationRuleHelper where T: Equatable { let validateFn: ((T?) -> ValidationError?) let rule: BaseRuleType } @@ -75,6 +75,8 @@ public struct RuleSet { public init() {} + /// Add a validation Rule to a Row + /// - Parameter rule: RuleType object typed to the same type of the Row.value public mutating func add(rule: Rule) where T == Rule.RowValueType { let validFn: ((T?) -> ValidationError?) = { (val: T?) in return rule.isValid(value: val) diff --git a/Pods/Eureka/Source/Rows/ActionSheetRow.swift b/Pods/Eureka/Source/Rows/ActionSheetRow.swift index 314e1ef..aed3070 100644 --- a/Pods/Eureka/Source/Rows/ActionSheetRow.swift +++ b/Pods/Eureka/Source/Rows/ActionSheetRow.swift @@ -24,7 +24,7 @@ import Foundation -open class AlertSelectorCell : Cell, CellType { +open class AlertSelectorCell : Cell, CellType where T: Equatable { required public init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) @@ -49,10 +49,12 @@ open class AlertSelectorCell : Cell, CellType { public class _ActionSheetRow: OptionsRow, PresenterRowType where Cell: BaseCell { - public var onPresentCallback: ((FormViewController, SelectorAlertController) -> Void)? - lazy public var presentationMode: PresentationMode>? = { + public typealias ProviderType = SelectorAlertController<_ActionSheetRow> + + public var onPresentCallback: ((FormViewController, ProviderType) -> Void)? + lazy public var presentationMode: PresentationMode? = { return .presentModally(controllerProvider: ControllerProvider.callback { [weak self] in - let vc = SelectorAlertController(title: self?.selectorTitle, message: nil, preferredStyle: .actionSheet) + let vc = SelectorAlertController<_ActionSheetRow>(title: self?.selectorTitle, message: nil, preferredStyle: .actionSheet) if let popView = vc.popoverPresentationController { guard let cell = self?.cell, let tableView = cell.formViewController()?.tableView else { fatalError() } popView.sourceView = tableView @@ -86,7 +88,7 @@ public class _ActionSheetRow: OptionsRow, PresenterRowType } /// An options row where the user can select an option from an ActionSheet -public final class ActionSheetRow: _ActionSheetRow>, RowType { +public final class ActionSheetRow: _ActionSheetRow>, RowType where T: Equatable { required public init(tag: String?) { super.init(tag: tag) } diff --git a/Pods/Eureka/Source/Rows/AlertRow.swift b/Pods/Eureka/Source/Rows/AlertRow.swift index baba0d3..ee2c8ab 100644 --- a/Pods/Eureka/Source/Rows/AlertRow.swift +++ b/Pods/Eureka/Source/Rows/AlertRow.swift @@ -23,12 +23,15 @@ // THE SOFTWARE. import Foundation + open class _AlertRow: OptionsRow, PresenterRowType where Cell: BaseCell { - open var onPresentCallback: ((FormViewController, SelectorAlertController) -> Void)? - lazy open var presentationMode: PresentationMode>? = { - return .presentModally(controllerProvider: ControllerProvider.callback { [weak self] in - let vc = SelectorAlertController(title: self?.selectorTitle, message: nil, preferredStyle: .alert) + public typealias PresentedController = SelectorAlertController<_AlertRow> + + open var onPresentCallback: ((FormViewController, PresentedController) -> Void)? + lazy open var presentationMode: PresentationMode? = { + return .presentModally(controllerProvider: ControllerProvider.callback { [weak self] in + let vc = PresentedController(title: self?.selectorTitle, message: nil, preferredStyle: .alert) vc.row = self return vc }, onDismiss: { [weak self] in diff --git a/Pods/Eureka/Source/Rows/Common/DateFieldRow.swift b/Pods/Eureka/Source/Rows/Common/DateFieldRow.swift index 8cb564c..e2ee1a1 100644 --- a/Pods/Eureka/Source/Rows/Common/DateFieldRow.swift +++ b/Pods/Eureka/Source/Rows/Common/DateFieldRow.swift @@ -82,7 +82,7 @@ open class DateCell: Cell, CellType { return datePicker } - func datePickerValueChanged(_ sender: UIDatePicker) { + @objc func datePickerValueChanged(_ sender: UIDatePicker) { row.value = sender.date detailTextLabel?.text = row.displayValueFor?(row.value) } diff --git a/Pods/Eureka/Source/Rows/Common/DecimalFormatter.swift b/Pods/Eureka/Source/Rows/Common/DecimalFormatter.swift index 24ec9aa..68c9705 100644 --- a/Pods/Eureka/Source/Rows/Common/DecimalFormatter.swift +++ b/Pods/Eureka/Source/Rows/Common/DecimalFormatter.swift @@ -24,8 +24,10 @@ import Foundation +/// A custom formatter for numbers with two digits after the decimal mark open class DecimalFormatter: NumberFormatter, FormatterProtocol { + /// Creates the formatter with 2 Fraction Digits, Locale set to .current and .decimal NumberFormatter.Style public override init() { super.init() locale = Locale.current @@ -38,9 +40,15 @@ open class DecimalFormatter: NumberFormatter, FormatterProtocol { fatalError("init(coder:) has not been implemented") } + /// Creates an NSNumber from the given String + /// - Parameter obj: Pointer to NSNumber object to assign + /// - Parameter for: String with number assumed to have the configured min. fraction digits. + /// - Parameter range: Unused range parameter override open func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer?, for string: String, range rangep: UnsafeMutablePointer?) throws { guard obj != nil else { return } let str = string.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "") + // Recover the number from the string in a way that forces the formatter's fraction digits + // numberWithoutDecimals / 10 ^ minimumFractionDigits obj?.pointee = NSNumber(value: (Double(str) ?? 0.0)/Double(pow(10.0, Double(minimumFractionDigits)))) } diff --git a/Pods/Eureka/Source/Rows/Common/FieldRow.swift b/Pods/Eureka/Source/Rows/Common/FieldRow.swift index a74303e..5f5b092 100644 --- a/Pods/Eureka/Source/Rows/Common/FieldRow.swift +++ b/Pods/Eureka/Source/Rows/Common/FieldRow.swift @@ -28,10 +28,10 @@ public protocol InputTypeInitiable { init?(string stringValue: String) } -public protocol FieldRowConformance: FormatterConformance { - var textFieldPercentage: CGFloat? { get set } - var placeholder: String? { get set } - var placeholderColor: UIColor? { get set } +public protocol FieldRowConformance : FormatterConformance { + var titlePercentage : CGFloat? { get set } + var placeholder : String? { get set } + var placeholderColor : UIColor? { get set } } extension Int: InputTypeInitiable { @@ -86,8 +86,19 @@ open class FieldRow: FormatteableRow, FieldRowConformance, open var keyboardReturnType: KeyboardReturnTypeConfiguration? /// The percentage of the cell that should be occupied by the textField - open var textFieldPercentage: CGFloat? - + @available (*, deprecated, message: "Use titleLabelPercentage instead") + open var textFieldPercentage : CGFloat? { + get { + return titlePercentage.map { 1 - $0 } + } + set { + titlePercentage = newValue.map { 1 - $0 } + } + } + + /// The percentage of the cell that should be occupied by the title (i.e. the titleLabel and optional imageView combined) + open var titlePercentage: CGFloat? + /// The placeholder for the textField open var placeholder: String? @@ -126,7 +137,9 @@ open class _FieldCell : Cell, UITextFieldDelegate, TextFieldCell where T: private var awakeFromNibCalled = false open var dynamicConstraints = [NSLayoutConstraint]() - + + private var calculatedTitlePercentage: CGFloat = 0.7 + public required init(style: UITableViewCellStyle, reuseIdentifier: String?) { let textField = UITextField() @@ -137,8 +150,8 @@ open class _FieldCell : Cell, UITextFieldDelegate, TextFieldCell where T: titleLabel = self.textLabel titleLabel?.translatesAutoresizingMaskIntoConstraints = false - titleLabel?.setContentHuggingPriority(500, for: .horizontal) - titleLabel?.setContentCompressionResistancePriority(1000, for: .horizontal) + titleLabel?.setContentHuggingPriority(UILayoutPriority(rawValue: 500), for: .horizontal) + titleLabel?.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 1000), for: .horizontal) contentView.addSubview(titleLabel!) contentView.addSubview(textField) @@ -157,6 +170,7 @@ open class _FieldCell : Cell, UITextFieldDelegate, TextFieldCell where T: } NotificationCenter.default.addObserver(forName: Notification.Name.UIContentSizeCategoryDidChange, object: nil, queue: nil) { [weak self] _ in + self?.titleLabel = self?.textLabel self?.setNeedsUpdateConstraints() } } @@ -216,7 +230,7 @@ open class _FieldCell : Cell, UITextFieldDelegate, TextFieldCell where T: textField.font = .preferredFont(forTextStyle: .body) if let placeholder = (row as? FieldRowConformance)?.placeholder { if let color = (row as? FieldRowConformance)?.placeholderColor { - textField.attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [NSForegroundColorAttributeName: color]) + textField.attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [NSAttributedStringKey.foregroundColor: color]) } else { textField.placeholder = (row as? FieldRowConformance)?.placeholder } @@ -268,28 +282,31 @@ open class _FieldCell : Cell, UITextFieldDelegate, TextFieldCell where T: if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty { views["label"] = titleLabel dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: "H:[imageView]-(15)-[label]-[textField]-|", options: NSLayoutFormatOptions(), metrics: nil, views: views) - dynamicConstraints.append(NSLayoutConstraint(item: textField, - attribute: .width, - relatedBy: (row as? FieldRowConformance)?.textFieldPercentage != nil ? .equal : .greaterThanOrEqual, - toItem: contentView, - attribute: .width, - multiplier: (row as? FieldRowConformance)?.textFieldPercentage ?? 0.3, - constant: 0.0)) - } else { + dynamicConstraints.append(NSLayoutConstraint(item: titleLabel, + attribute: .width, + relatedBy: (row as? FieldRowConformance)?.titlePercentage != nil ? .equal : .lessThanOrEqual, + toItem: contentView, + attribute: .width, + multiplier: calculatedTitlePercentage, + constant: 0.0)) + } + else{ dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: "H:[imageView]-(15)-[textField]-|", options: [], metrics: nil, views: views) } - } else { - if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty { + } + else{ + if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty { views["label"] = titleLabel dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|-[label]-[textField]-|", options: [], metrics: nil, views: views) - dynamicConstraints.append(NSLayoutConstraint(item: textField, - attribute: .width, - relatedBy: (row as? FieldRowConformance)?.textFieldPercentage != nil ? .equal : .greaterThanOrEqual, - toItem: contentView, - attribute: .width, - multiplier: (row as? FieldRowConformance)?.textFieldPercentage ?? 0.3, - constant: 0.0)) - } else { + dynamicConstraints.append(NSLayoutConstraint(item: titleLabel, + attribute: .width, + relatedBy: (row as? FieldRowConformance)?.titlePercentage != nil ? .equal : .lessThanOrEqual, + toItem: contentView, + attribute: .width, + multiplier: calculatedTitlePercentage, + constant: 0.0)) + } + else{ dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|-[textField]-|", options: .alignAllLeft, metrics: nil, views: views) } } @@ -301,7 +318,7 @@ open class _FieldCell : Cell, UITextFieldDelegate, TextFieldCell where T: super.updateConstraints() } - open func textFieldDidChange(_ textField: UITextField) { + @objc open func textFieldDidChange(_ textField: UITextField) { guard let textValue = textField.text else { row.value = nil @@ -381,6 +398,27 @@ open class _FieldCell : Cell, UITextFieldDelegate, TextFieldCell where T: open func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { return formViewController()?.textInputShouldEndEditing(textField, cell: self) ?? true - } - + } + + open override func layoutSubviews() { + super.layoutSubviews() + guard let row = (row as? FieldRowConformance) else { return } + guard let titlePercentage = row.titlePercentage else { return } + var targetTitleWidth = bounds.size.width * titlePercentage + if let imageView = imageView, let _ = imageView.image, let titleLabel = titleLabel { + var extraWidthToSubtract = titleLabel.frame.minX - imageView.frame.minX // Left-to-right interface layout + if #available(iOS 9.0, *) { + if UIView.userInterfaceLayoutDirection(for: self.semanticContentAttribute) == .rightToLeft { + extraWidthToSubtract = imageView.frame.maxX - titleLabel.frame.maxX + } + } + targetTitleWidth -= extraWidthToSubtract + } + let targetTitlePercentage = targetTitleWidth / contentView.bounds.size.width + if calculatedTitlePercentage != targetTitlePercentage { + calculatedTitlePercentage = targetTitlePercentage + setNeedsUpdateConstraints() + updateConstraintsIfNeeded() + } + } } diff --git a/Pods/Eureka/Source/Rows/Common/GenericMultipleSelectorRow.swift b/Pods/Eureka/Source/Rows/Common/GenericMultipleSelectorRow.swift index ea812d6..2dae023 100644 --- a/Pods/Eureka/Source/Rows/Common/GenericMultipleSelectorRow.swift +++ b/Pods/Eureka/Source/Rows/Common/GenericMultipleSelectorRow.swift @@ -25,32 +25,34 @@ import Foundation /// Generic options selector row that allows multiple selection. -open class GenericMultipleSelectorRow: Row, PresenterRowType, NoValueDisplayTextConformance - where Cell: BaseCell, Cell.Value == Set, VCType: UIViewController, VCType.RowValue == Set { +open class GenericMultipleSelectorRow: Row, PresenterRowType, NoValueDisplayTextConformance, OptionsProviderRow + where Cell: BaseCell, Cell.Value == Set { + + public typealias PresentedController = MultipleSelectorViewController> /// Defines how the view controller will be presented, pushed, etc. - open var presentationMode: PresentationMode? + open var presentationMode: PresentationMode? /// Will be called before the presentation occurs. - open var onPresentCallback: ((FormViewController, VCType) -> Void)? + open var onPresentCallback: ((FormViewController, PresentedController) -> Void)? /// Title to be displayed for the options open var selectorTitle: String? open var noValueDisplayText: String? /// Options from which the user will choose - open var options: [T] { - get { return self.dataProvider?.arrayData?.map({ $0.first! }) ?? [] } - set { self.dataProvider = DataProvider(arrayData: newValue.map({ Set(arrayLiteral: $0) })) } - } + open var optionsProvider: OptionsProvider? required public init(tag: String?) { super.init(tag: tag) displayValueFor = { (rowValue: Set?) in return rowValue?.map({ String(describing: $0) }).sorted().joined(separator: ", ") } - presentationMode = .show(controllerProvider: ControllerProvider.callback { return VCType() }, onDismiss: { vc in - let _ = vc.navigationController?.popViewController(animated: true) }) + presentationMode = .show(controllerProvider: ControllerProvider.callback { + return MultipleSelectorViewController>() + }, onDismiss: { vc in + let _ = vc.navigationController?.popViewController(animated: true) + }) } /** @@ -74,7 +76,7 @@ open class GenericMultipleSelectorRow : Row, NoValueDisplayTextConformance where Cell: BaseCell { +open class OptionsRow : Row, NoValueDisplayTextConformance, OptionsProviderRow where Cell: BaseCell { + - open var options: [Cell.Value] { - get { return dataProvider?.arrayData ?? [] } - set { dataProvider = DataProvider(arrayData: newValue) } - } + open var optionsProvider: OptionsProvider? + open var selectorTitle: String? open var noValueDisplayText: String? diff --git a/Pods/Eureka/Source/Rows/Common/SelectorRow.swift b/Pods/Eureka/Source/Rows/Common/SelectorRow.swift index 422fa28..9dfae00 100644 --- a/Pods/Eureka/Source/Rows/Common/SelectorRow.swift +++ b/Pods/Eureka/Source/Rows/Common/SelectorRow.swift @@ -43,13 +43,16 @@ open class PushSelectorCell : Cell, CellType { } /// Generic row type where a user must select a value among several options. -open class SelectorRow: OptionsRow, PresenterRowType where Cell: BaseCell, VCType: UIViewController, VCType.RowValue == Cell.Value { +open class SelectorRow: OptionsRow, PresenterRowType where Cell: BaseCell { + + public typealias PresenterRow = SelectorViewController> + /// Defines how the view controller will be presented, pushed, etc. - open var presentationMode: PresentationMode? + open var presentationMode: PresentationMode? /// Will be called before the presentation occurs. - open var onPresentCallback: ((FormViewController, VCType) -> Void)? + open var onPresentCallback: ((FormViewController, PresenterRow) -> Void)? required public init(tag: String?) { super.init(tag: tag) @@ -76,7 +79,7 @@ open class SelectorRow: OptionsR */ open override func prepare(for segue: UIStoryboardSegue) { super.prepare(for: segue) - guard let rowVC = segue.destination as? VCType else { return } + guard let rowVC = segue.destination as? PresenterRow else { return } rowVC.title = selectorTitle ?? rowVC.title rowVC.onDismissCallback = presentationMode?.onDismissCallback ?? rowVC.onDismissCallback onPresentCallback?(cell.formViewController()!, rowVC) diff --git a/Pods/Eureka/Source/Rows/Controllers/MultipleSelectorViewController.swift b/Pods/Eureka/Source/Rows/Controllers/MultipleSelectorViewController.swift index 89268b4..bf96cc9 100644 --- a/Pods/Eureka/Source/Rows/Controllers/MultipleSelectorViewController.swift +++ b/Pods/Eureka/Source/Rows/Controllers/MultipleSelectorViewController.swift @@ -25,10 +25,10 @@ import Foundation /// Selector Controller that enables multiple selection -open class _MultipleSelectorViewController : FormViewController, TypedRowControllerType where Row: BaseRow, Row: TypedRowType, Row.Cell.Value == T { +open class _MultipleSelectorViewController : FormViewController, TypedRowControllerType where Row: BaseRow, Row.Cell.Value == OptionsRow.OptionsProviderType.Option, OptionsRow.OptionsProviderType.Option: Hashable { /// The row that pushed or presented this controller - public var row: RowOf>! + public var row: RowOf>! public var selectableRowCellSetup: ((_ cell: Row.Cell, _ row: Row) -> Void)? public var selectableRowCellUpdate: ((_ cell: Row.Cell, _ row: Row) -> Void)? @@ -47,6 +47,12 @@ open class _MultipleSelectorViewController /// A closure that returns footer title for a section for particular key. public var sectionFooterTitleForKey: ((String) -> String?)? + + public var optionsProviderRow: OptionsRow { + return row as! OptionsRow + } + + override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } @@ -66,34 +72,44 @@ open class _MultipleSelectorViewController } open func setupForm() { - guard let options = row.dataProvider?.arrayData else { return } - - if let optionsBySections = self.optionsBySections() { + optionsProviderRow.optionsProvider?.options(for: self) { [weak self] (options: [OptionsRow.OptionsProviderType.Option]?) in + guard let strongSelf = self, let options = options else { return } + strongSelf.optionsProviderRow.cachedOptionsData = options + strongSelf.setupForm(with: options) + } + } + + open func setupForm(with options: [OptionsRow.OptionsProviderType.Option]) { + if let optionsBySections = optionsBySections(with: options) { for (sectionKey, options) in optionsBySections { - form +++ section(with: options, header: sectionHeaderTitleForKey?(sectionKey), footer: sectionFooterTitleForKey?(sectionKey)) + form +++ section(with: options, + header: sectionHeaderTitleForKey?(sectionKey), + footer: sectionFooterTitleForKey?(sectionKey)) } } else { form +++ section(with: options, header: row.title, footer: nil) } } + + open func optionsBySections(with options: [OptionsRow.OptionsProviderType.Option]) -> [(String, [Row.Cell.Value])]? { + guard let sectionKeyForValue = sectionKeyForValue else { return nil } - open func optionsBySections() -> [(String, [Set])]? { - guard let options = row.dataProvider?.arrayData, let sectionKeyForValue = sectionKeyForValue else { return nil } - - let sections = options.reduce([:]) { (reduced, option) -> [String: [Set]] in + let sections = options.reduce([:]) { (reduced, option) -> [String: [Row.Cell.Value]] in var reduced = reduced - let key = sectionKeyForValue(option.first!) - reduced[key] = (reduced[key] ?? []) + [option] + let key = sectionKeyForValue(options.first!) + var items = reduced[key] ?? [] + items.append(option) + reduced[key] = items return reduced } return sections.sorted(by: { (lhs, rhs) in lhs.0 < rhs.0 }) } - func section(with options: [Set], header: String?, footer: String?) -> SelectableSection { + func section(with options: [OptionsRow.OptionsProviderType.Option], header: String?, footer: String?) -> SelectableSection { let section = SelectableSection(header: header ?? "", footer: footer ?? "", selectionType: .multipleSelection) { [weak self] section in section.onSelectSelectableRow = { _, selectableRow in - var newValue: Set = self?.row.value ?? [] + var newValue: Set = self?.row.value ?? [] if let selectableValue = selectableRow.value { newValue.insert(selectableValue) } else { @@ -104,9 +120,9 @@ open class _MultipleSelectorViewController } for option in options { section <<< Row.init { lrow in - lrow.title = String(describing: option.first!) - lrow.selectableValue = option.first! - lrow.value = self.row.value?.contains(option.first!) ?? false ? option.first! : nil + lrow.title = String(describing: option) + lrow.selectableValue = option + lrow.value = self.row.value?.contains(option) ?? false ? option : nil }.cellSetup { [weak self] cell, row in self?.selectableRowCellSetup?(cell, row) }.cellUpdate { [weak self] cell, row in @@ -117,5 +133,14 @@ open class _MultipleSelectorViewController } } -open class MultipleSelectorViewController : _MultipleSelectorViewController> { +open class MultipleSelectorViewController: _MultipleSelectorViewController, OptionsRow> where OptionsRow.OptionsProviderType.Option: Hashable{ + + override public init(nibName nibNameOrNil: String? = nil, bundle nibBundleOrNil: Bundle? = nil) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + } diff --git a/Pods/Eureka/Source/Rows/Controllers/SelectorAlertController.swift b/Pods/Eureka/Source/Rows/Controllers/SelectorAlertController.swift index 15d3585..f38520b 100644 --- a/Pods/Eureka/Source/Rows/Controllers/SelectorAlertController.swift +++ b/Pods/Eureka/Source/Rows/Controllers/SelectorAlertController.swift @@ -25,15 +25,22 @@ import Foundation /// Selector UIAlertController -open class SelectorAlertController : UIAlertController, TypedRowControllerType { +open class SelectorAlertController: UIAlertController, TypedRowControllerType where OptionsRow.OptionsProviderType.Option == OptionsRow.Cell.Value, OptionsRow: BaseRow { /// The row that pushed or presented this controller - public var row: RowOf! + public var row: RowOf! public var cancelTitle = NSLocalizedString("Cancel", comment: "") /// A closure to be called when the controller disappears. public var onDismissCallback: ((UIViewController) -> Void)? + + /// Options provider to use to get available options. + /// If not set will use synchronous data provider built with `row.dataProvider.arrayData`. + // public var optionsProvider: OptionsProvider? + public var optionsProviderRow: OptionsRow { + return row as! OptionsRow + } override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) @@ -50,7 +57,7 @@ open class SelectorAlertController : UIAlertController, TypedRowCo open override func viewDidLoad() { super.viewDidLoad() - guard let options = row.dataProvider?.arrayData else { return } + guard let options = optionsProviderRow.options else { return } addAction(UIAlertAction(title: cancelTitle, style: .cancel, handler: nil)) for option in options { addAction(UIAlertAction(title: row.displayValueFor?(option), style: .default, handler: { [weak self] _ in diff --git a/Pods/Eureka/Source/Rows/Controllers/SelectorViewController.swift b/Pods/Eureka/Source/Rows/Controllers/SelectorViewController.swift index 5a03002..3674089 100644 --- a/Pods/Eureka/Source/Rows/Controllers/SelectorViewController.swift +++ b/Pods/Eureka/Source/Rows/Controllers/SelectorViewController.swift @@ -24,7 +24,86 @@ import Foundation -open class _SelectorViewController: FormViewController, TypedRowControllerType where Row: BaseRow, Row: TypedRowType { + +/** + * Responsible for the options passed to a selector view controller + */ + +public protocol OptionsProviderRow: TypedRowType { + associatedtype OptionsProviderType: OptionsProviderConformance + + var optionsProvider: OptionsProviderType? { get set } + + var cachedOptionsData: [OptionsProviderType.Option]? { get set } +} + +extension OptionsProviderRow where Self: BaseRow { + + public var options: [OptionsProviderType.Option]? { + set (newValue){ + let optProvider = OptionsProviderType.init(array: newValue) + optionsProvider = optProvider + } + get { + return self.cachedOptionsData ?? optionsProvider?.optionsArray + } + } + + public var cachedOptionsData: [OptionsProviderType.Option]? { + get { + return self._cachedOptionsData as? [OptionsProviderType.Option] + } + set { + self._cachedOptionsData = newValue + } + } +} + +public protocol OptionsProviderConformance: ExpressibleByArrayLiteral { + associatedtype Option: Equatable + + init(array: [Option]?) + func options(for selectorViewController: FormViewController, completion: @escaping ([Option]?) -> Void) + var optionsArray: [Option]? { get } + +} + +/// Provider of selectable options. +public enum OptionsProvider: OptionsProviderConformance { + + /// Synchronous provider that provides array of options it was initialized with + case array([T]?) + /// Provider that uses closure it was initialized with to provide options. Can be synchronous or asynchronous. + case lazy((FormViewController, @escaping ([T]?) -> Void) -> Void) + + public init(array: [T]?) { + self = .array(array) + } + + public init(arrayLiteral elements: T...) { + self = .array(elements) + } + + public func options(for selectorViewController: FormViewController, completion: @escaping ([T]?) -> Void) { + switch self { + case let .array(array): + completion(array) + case let .lazy(fetch): + fetch(selectorViewController, completion) + } + } + + public var optionsArray: [T]?{ + switch self { + case let .array(arrayData): + return arrayData + default: + return nil + } + } +} + +open class _SelectorViewController: FormViewController, TypedRowControllerType where Row: BaseRow, Row.Cell.Value == OptionsRow.OptionsProviderType.Option { /// The row that pushed or presented this controller public var row: RowOf! @@ -48,6 +127,14 @@ open class _SelectorViewController: FormViewController, /// A closure that returns footer title for a section for particular key. public var sectionFooterTitleForKey: ((String) -> String?)? + + public var optionsProviderRow: OptionsRow { + return row as! OptionsRow + } + + override public init(style: UITableViewStyle) { + super.init(style: style) + } override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) @@ -68,19 +155,28 @@ open class _SelectorViewController: FormViewController, } open func setupForm() { - guard let options = row.dataProvider?.arrayData else { return } - - if let optionsBySections = self.optionsBySections() { + let optProvider = optionsProviderRow.optionsProvider + optProvider?.options(for: self) { [weak self] (options: [Row.Cell.Value]?) in + guard let strongSelf = self, let options = options else { return } + strongSelf.optionsProviderRow.cachedOptionsData = options + strongSelf.setupForm(with: options) + } + } + + open func setupForm(with options: [Row.Cell.Value]) { + if let optionsBySections = optionsBySections(with: options) { for (sectionKey, options) in optionsBySections { - form +++ section(with: options, header: sectionHeaderTitleForKey?(sectionKey), footer: sectionFooterTitleForKey?(sectionKey)) + form +++ section(with: options, + header: sectionHeaderTitleForKey?(sectionKey), + footer: sectionFooterTitleForKey?(sectionKey)) } } else { form +++ section(with: options, header: row.title, footer: nil) } } - - func optionsBySections() -> [(String, [Row.Cell.Value])]? { - guard let options = row.dataProvider?.arrayData, let sectionKeyForValue = sectionKeyForValue else { return nil } + + func optionsBySections(with options: [Row.Cell.Value]) -> [(String, [Row.Cell.Value])]? { + guard let sectionKeyForValue = sectionKeyForValue else { return nil } let sections = options.reduce([:]) { (reduced, option) -> [String: [Row.Cell.Value]] in var reduced = reduced @@ -99,6 +195,17 @@ open class _SelectorViewController: FormViewController, section.onSelectSelectableRow = { _, row in let changed = self?.row.value != row.value self?.row.value = row.value + + if let form = row.section?.form { + for section in form where section !== row.section { + let section = section as! SelectableSection + if let selectedRow = section.selectedRow(), selectedRow !== row { + selectedRow.value = nil + selectedRow.updateCell() + } + } + } + if self?.dismissOnSelection == true || (changed && self?.dismissOnChange == true) { self?.onDismissCallback?(self!) } @@ -121,5 +228,5 @@ open class _SelectorViewController: FormViewController, } /// Selector Controller (used to select one option among a list) -open class SelectorViewController : _SelectorViewController> { +open class SelectorViewController: _SelectorViewController, OptionsRow> { } diff --git a/Pods/Eureka/Source/Rows/DatePickerRow.swift b/Pods/Eureka/Source/Rows/DatePickerRow.swift index eb16e3d..1782657 100644 --- a/Pods/Eureka/Source/Rows/DatePickerRow.swift +++ b/Pods/Eureka/Source/Rows/DatePickerRow.swift @@ -49,6 +49,7 @@ open class DatePickerCell: Cell, CellType { selectionStyle = .none accessoryType = .none editingAccessoryType = .none + height = { UITableViewAutomaticDimension } datePicker.datePickerMode = datePickerMode() datePicker.addTarget(self, action: #selector(DatePickerCell.datePickerValueChanged(_:)), for: .valueChanged) } @@ -71,7 +72,7 @@ open class DatePickerCell: Cell, CellType { } } - func datePickerValueChanged(_ sender: UIDatePicker) { + @objc func datePickerValueChanged(_ sender: UIDatePicker) { row?.value = sender.date } diff --git a/Pods/Eureka/Source/Rows/MultipleSelectorRow.swift b/Pods/Eureka/Source/Rows/MultipleSelectorRow.swift index 30c2b21..466a285 100644 --- a/Pods/Eureka/Source/Rows/MultipleSelectorRow.swift +++ b/Pods/Eureka/Source/Rows/MultipleSelectorRow.swift @@ -24,7 +24,7 @@ import Foundation -open class _MultipleSelectorRow: GenericMultipleSelectorRow> where Cell: BaseCell, Cell: TypedCellType, Cell.Value == Set { +open class _MultipleSelectorRow: GenericMultipleSelectorRow where Cell: BaseCell, Cell.Value == Set { public required init(tag: String?) { super.init(tag: tag) } diff --git a/Pods/Eureka/Source/Rows/PickerInlineRow.swift b/Pods/Eureka/Source/Rows/PickerInlineRow.swift index 4ecf88e..0a7e855 100644 --- a/Pods/Eureka/Source/Rows/PickerInlineRow.swift +++ b/Pods/Eureka/Source/Rows/PickerInlineRow.swift @@ -88,5 +88,6 @@ public final class PickerInlineRow : _PickerInlineRow, RowType, InlineRowT public func setupInlineRow(_ inlineRow: InlineRow) { inlineRow.options = self.options inlineRow.displayValueFor = self.displayValueFor + inlineRow.cell.height = { UITableViewAutomaticDimension } } } diff --git a/Pods/Eureka/Source/Rows/PickerInputRow.swift b/Pods/Eureka/Source/Rows/PickerInputRow.swift index 274885e..9bda369 100644 --- a/Pods/Eureka/Source/Rows/PickerInputRow.swift +++ b/Pods/Eureka/Source/Rows/PickerInputRow.swift @@ -26,7 +26,7 @@ import Foundation // MARK: PickerInputCell -open class PickerInputCell : Cell, CellType, UIPickerViewDataSource, UIPickerViewDelegate where T: Equatable, T: InputTypeInitiable { +open class PickerInputCell : Cell, CellType, UIPickerViewDataSource, UIPickerViewDelegate where T: Equatable, T: InputTypeInitiable { lazy public var picker: UIPickerView = { let picker = UIPickerView() diff --git a/Pods/Eureka/Source/Rows/PickerRow.swift b/Pods/Eureka/Source/Rows/PickerRow.swift index 3a9e06a..00b846f 100644 --- a/Pods/Eureka/Source/Rows/PickerRow.swift +++ b/Pods/Eureka/Source/Rows/PickerRow.swift @@ -52,6 +52,7 @@ open class PickerCell : Cell, CellType, UIPickerViewDataSource, UIPickerVi super.setup() accessoryType = .none editingAccessoryType = .none + height = { UITableViewAutomaticDimension } picker.delegate = self picker.dataSource = self } diff --git a/Pods/Eureka/Source/Rows/PopoverSelectorRow.swift b/Pods/Eureka/Source/Rows/PopoverSelectorRow.swift index d80e821..1cdf861 100644 --- a/Pods/Eureka/Source/Rows/PopoverSelectorRow.swift +++ b/Pods/Eureka/Source/Rows/PopoverSelectorRow.swift @@ -24,7 +24,7 @@ import Foundation -open class _PopoverSelectorRow : SelectorRow> where Cell: BaseCell, Cell: TypedCellType { +open class _PopoverSelectorRow : SelectorRow where Cell: BaseCell { public required init(tag: String?) { super.init(tag: tag) @@ -35,7 +35,7 @@ open class _PopoverSelectorRow : SelectorRow { _ in } }, onDismiss: { [weak self] in + presentationMode = .popover(controllerProvider: ControllerProvider.callback { return SelectorViewController> { _ in } }, onDismiss: { [weak self] in $0.dismiss(animated: true) self?.reload() }) diff --git a/Pods/Eureka/Source/Rows/PushRow.swift b/Pods/Eureka/Source/Rows/PushRow.swift index 2276621..ef92965 100644 --- a/Pods/Eureka/Source/Rows/PushRow.swift +++ b/Pods/Eureka/Source/Rows/PushRow.swift @@ -24,11 +24,11 @@ import Foundation -open class _PushRow : SelectorRow> where Cell: BaseCell { +open class _PushRow: SelectorRow where Cell: BaseCell { public required init(tag: String?) { super.init(tag: tag) - presentationMode = .show(controllerProvider: ControllerProvider.callback { return SelectorViewController { _ in } }, onDismiss: { vc in + presentationMode = .show(controllerProvider: ControllerProvider.callback { return SelectorViewController> { _ in } }, onDismiss: { vc in let _ = vc.navigationController?.popViewController(animated: true) }) } } diff --git a/Pods/Eureka/Source/Rows/SegmentedRow.swift b/Pods/Eureka/Source/Rows/SegmentedRow.swift index 0bf7de0..3f9998a 100644 --- a/Pods/Eureka/Source/Rows/SegmentedRow.swift +++ b/Pods/Eureka/Source/Rows/SegmentedRow.swift @@ -40,12 +40,12 @@ open class SegmentedCell : Cell, CellType { let segmentedControl = UISegmentedControl() segmentedControl.translatesAutoresizingMaskIntoConstraints = false - segmentedControl.setContentHuggingPriority(250, for: .horizontal) + segmentedControl.setContentHuggingPriority(UILayoutPriority(rawValue: 250), for: .horizontal) self.segmentedControl = segmentedControl self.titleLabel = self.textLabel self.titleLabel?.translatesAutoresizingMaskIntoConstraints = false - self.titleLabel?.setContentHuggingPriority(500, for: .horizontal) + self.titleLabel?.setContentHuggingPriority(UILayoutPriority(rawValue: 500), for: .horizontal) NotificationCenter.default.addObserver(forName: Notification.Name.UIApplicationWillResignActive, object: nil, queue: nil) { [weak self] _ in guard let me = self else { return } @@ -61,6 +61,7 @@ open class SegmentedCell : Cell, CellType { } NotificationCenter.default.addObserver(forName: Notification.Name.UIContentSizeCategoryDidChange, object: nil, queue: nil) { [weak self] _ in + self?.titleLabel = self?.textLabel self?.setNeedsUpdateConstraints() } contentView.addSubview(titleLabel!) @@ -98,7 +99,6 @@ open class SegmentedCell : Cell, CellType { open override func setup() { super.setup() - height = { BaseRow.estimatedRowHeight } selectionStyle = .none segmentedControl.addTarget(self, action: #selector(SegmentedCell.valueChanged), for: .valueChanged) } @@ -112,8 +112,8 @@ open class SegmentedCell : Cell, CellType { segmentedControl.isEnabled = !row.isDisabled } - func valueChanged() { - row.value = (row as! SegmentedRow).options[segmentedControl.selectedSegmentIndex] + @objc func valueChanged() { + row.value = (row as! SegmentedRow).options?[segmentedControl.selectedSegmentIndex] } open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { @@ -128,7 +128,14 @@ open class SegmentedCell : Cell, CellType { func updateSegmentedControl() { segmentedControl.removeAllSegments() - items().enumerated().forEach { segmentedControl.insertSegment(withTitle: $0.element, at: $0.offset, animated: false) } + + (row as! SegmentedRow).options?.reversed().forEach { + if let image = $0 as? UIImage { + segmentedControl.insertSegment(with: image, at: 0, animated: false) + } else { + segmentedControl.insertSegment(withTitle: row.displayValueFor?($0) ?? "", at: 0, animated: false) + } + } } open override func updateConstraints() { @@ -166,17 +173,9 @@ open class SegmentedCell : Cell, CellType { super.updateConstraints() } - func items() -> [String] {// or create protocol for options - var result = [String]() - for object in (row as! SegmentedRow).options { - result.append(row.displayValueFor?(object) ?? "") - } - return result - } - func selectedIndex() -> Int? { guard let value = row.value else { return nil } - return (row as! SegmentedRow).options.index(of: value) + return (row as! SegmentedRow).options?.index(of: value) } } diff --git a/Pods/Eureka/Source/Rows/SelectableRows/ListCheckRow.swift b/Pods/Eureka/Source/Rows/SelectableRows/ListCheckRow.swift index 847d997..496f3de 100644 --- a/Pods/Eureka/Source/Rows/SelectableRows/ListCheckRow.swift +++ b/Pods/Eureka/Source/Rows/SelectableRows/ListCheckRow.swift @@ -62,7 +62,7 @@ open class ListCheckCell : Cell, CellType { } -public final class ListCheckRow: Row>, SelectableRowType, RowType { +public final class ListCheckRow: Row>, SelectableRowType, RowType where T: Equatable { public var selectableValue: T? required public init(tag: String?) { super.init(tag: tag) diff --git a/Pods/Eureka/Source/Rows/SliderRow.swift b/Pods/Eureka/Source/Rows/SliderRow.swift index 69216a6..5bc2826 100644 --- a/Pods/Eureka/Source/Rows/SliderRow.swift +++ b/Pods/Eureka/Source/Rows/SliderRow.swift @@ -41,8 +41,8 @@ open class SliderCell: Cell, CellType { NotificationCenter.default.addObserver(forName: Notification.Name.UIContentSizeCategoryDidChange, object: nil, queue: nil) { [weak self] _ in guard let me = self else { return } if me.shouldShowTitle { - me.contentView.addSubview(me.titleLabel) - me.contentView.addSubview(me.valueLabel!) + me.titleLabel = me.textLabel + me.valueLabel = me.detailTextLabel me.addConstraints() } } @@ -64,17 +64,17 @@ open class SliderCell: Cell, CellType { // title let title = textLabel textLabel?.translatesAutoresizingMaskIntoConstraints = false - textLabel?.setContentHuggingPriority(500, for: .horizontal) + textLabel?.setContentHuggingPriority(UILayoutPriority(rawValue: 500), for: .horizontal) self.titleLabel = title let value = detailTextLabel value?.translatesAutoresizingMaskIntoConstraints = false - value?.setContentHuggingPriority(500, for: .horizontal) + value?.setContentHuggingPriority(UILayoutPriority(rawValue: 500), for: .horizontal) self.valueLabel = value let slider = UISlider() slider.translatesAutoresizingMaskIntoConstraints = false - slider.setContentHuggingPriority(500, for: .horizontal) + slider.setContentHuggingPriority(UILayoutPriority(rawValue: 500), for: .horizontal) self.slider = slider if shouldShowTitle { @@ -97,25 +97,25 @@ open class SliderCell: Cell, CellType { valueLabel.isHidden = !shouldShowTitle && !awakeFromNibCalled titleLabel.isHidden = valueLabel.isHidden slider.value = row.value ?? 0.0 + slider.isEnabled = !row.isDisabled } func addConstraints() { guard !awakeFromNibCalled else { return } + let views: [String : Any] = ["titleLabel": titleLabel, "valueLabel": valueLabel, "slider": slider] - //TODO: in Iphone 6 Plus hPadding should be 20 - let metrics = ["hPadding": 15.0, "vPadding": 12.0, "spacing": 12.0] + let metrics = ["vPadding": 12.0, "spacing": 12.0] if shouldShowTitle { - contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-hPadding-[titleLabel]-[valueLabel]-hPadding-|", options: NSLayoutFormatOptions.alignAllLastBaseline, metrics: metrics, views: views)) + contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[titleLabel]-[valueLabel]-|", options: NSLayoutFormatOptions.alignAllLastBaseline, metrics: metrics, views: views)) contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-vPadding-[titleLabel]-spacing-[slider]-vPadding-|", options: NSLayoutFormatOptions.alignAllLeft, metrics: metrics, views: views)) - } else { contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-vPadding-[slider]-vPadding-|", options: NSLayoutFormatOptions.alignAllLeft, metrics: metrics, views: views)) } - contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-hPadding-[slider]-hPadding-|", options: NSLayoutFormatOptions.alignAllLastBaseline, metrics: metrics, views: views)) + contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[slider]-|", options: NSLayoutFormatOptions.alignAllLastBaseline, metrics: metrics, views: views)) } - func valueChanged() { + @objc func valueChanged() { let roundedValue: Float let steps = Float(sliderRow.steps) if steps > 0 { diff --git a/Pods/Eureka/Source/Rows/StepperRow.swift b/Pods/Eureka/Source/Rows/StepperRow.swift index c40dd61..24837e5 100644 --- a/Pods/Eureka/Source/Rows/StepperRow.swift +++ b/Pods/Eureka/Source/Rows/StepperRow.swift @@ -33,8 +33,6 @@ open class StepperCell: Cell, CellType { addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[v]-[s]-|", options: .alignAllCenterY, metrics: nil, views: ["s": stepper, "v": valueLabel])) addConstraint(NSLayoutConstraint(item: stepper, attribute: .centerY, relatedBy: .equal, toItem: contentView, attribute: .centerY, multiplier: 1.0, constant: 0)) addConstraint(NSLayoutConstraint(item: valueLabel, attribute: .centerY, relatedBy: .equal, toItem: stepper, attribute: .centerY, multiplier: 1.0, constant: 0)) - - height = { BaseRow.estimatedRowHeight } } required public init?(coder aDecoder: NSCoder) { @@ -63,7 +61,7 @@ open class StepperCell: Cell, CellType { detailTextLabel?.text = nil } - func valueChanged() { + @objc func valueChanged() { row.value = stepper.value row.updateCell() } diff --git a/Pods/Eureka/Source/Rows/SwitchRow.swift b/Pods/Eureka/Source/Rows/SwitchRow.swift index f37f115..e54f903 100644 --- a/Pods/Eureka/Source/Rows/SwitchRow.swift +++ b/Pods/Eureka/Source/Rows/SwitchRow.swift @@ -58,7 +58,7 @@ open class SwitchCell: Cell, CellType { switchControl.isEnabled = !row.isDisabled } - func valueChanged() { + @objc func valueChanged() { row.value = switchControl?.isOn ?? false } } diff --git a/Pods/Eureka/Source/Validations/RuleLength.swift b/Pods/Eureka/Source/Validations/RuleLength.swift index 71e4262..9d10fbb 100644 --- a/Pods/Eureka/Source/Validations/RuleLength.swift +++ b/Pods/Eureka/Source/Validations/RuleLength.swift @@ -61,3 +61,21 @@ public struct RuleMaxLength: RuleType { return value.characters.count > Int(max) ? validationError : nil } } + +public struct RuleExactLength: RuleType { + let length: UInt + + public var id: String? + public var validationError: ValidationError + + public init(exactLength: UInt, msg: String? = nil) { + let ruleMsg = msg ?? "Field value must have exactly \(exactLength) characters" + length = exactLength + validationError = ValidationError(msg: ruleMsg) + } + + public func isValid(value: String?) -> ValidationError? { + guard let value = value else { return nil } + return value.characters.count != Int(length) ? validationError : nil + } +} diff --git a/Pods/Local Podspecs/Eureka.podspec.json b/Pods/Local Podspecs/Eureka.podspec.json index 94aff2c..4c75386 100644 --- a/Pods/Local Podspecs/Eureka.podspec.json +++ b/Pods/Local Podspecs/Eureka.podspec.json @@ -1,6 +1,6 @@ { "name": "Eureka", - "version": "3.0.0", + "version": "3.1.0", "license": "MIT", "summary": "Elegant iOS Forms in pure Swift", "homepage": "https://github.com/xmartlabs/Eureka", @@ -11,7 +11,7 @@ }, "source": { "git": "https://github.com/xmartlabs/Eureka.git", - "tag": "3.0.0" + "tag": "3.1.0" }, "platforms": { "ios": "8.0" diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock index aea47bd..3a19d58 100644 --- a/Pods/Manifest.lock +++ b/Pods/Manifest.lock @@ -1,25 +1,15 @@ PODS: - - Eureka (3.0.0) + - Eureka (4.0.0) - UIColor_Hex_Swift (3.0.2) DEPENDENCIES: - - Eureka (from `https://github.com/xmartlabs/Eureka.git`, branch `master`) - - UIColor_Hex_Swift (~> 3.0.2) - -EXTERNAL SOURCES: - Eureka: - :branch: master - :git: https://github.com/xmartlabs/Eureka.git - -CHECKOUT OPTIONS: - Eureka: - :commit: 77cb04f587a4e83f28ad5f3174f6f8f6c086b524 - :git: https://github.com/xmartlabs/Eureka.git + - Eureka (~> 4.0.0) + - UIColor_Hex_Swift SPEC CHECKSUMS: - Eureka: 5b9418d7bfdc21ca977d69d124a6409f3e9af2c7 + Eureka: c0b55d2aec82050c1400c7d65960b700be8d10ef UIColor_Hex_Swift: 95f718452092a3efc8a827dffd2c04d3237be02d -PODFILE CHECKSUM: af7f6296626bb44cb5f6bedfacf378f45aa2c098 +PODFILE CHECKSUM: 309386d4cd991af5cee3f3de160a3338b893ff73 -COCOAPODS: 1.2.1 +COCOAPODS: 1.3.1 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index 700cbcf..bd8468e 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -642,7 +642,7 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 4F46456883363212A9C9A60C24F1A42F /* Release */ = { + 03EB0770382FA058DE3E27FDEDF37AE6 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = F930180A7601440DC45A7552C98ED6A9 /* UIColor_Hex_Swift.xcconfig */; buildSettings = { @@ -668,17 +668,18 @@ PRODUCT_NAME = UIColor_Hex_Swift; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; - 622A647E88DD596D9378067D994EF4DD /* Release */ = { + 2F5EB86BB29399CECCB7751986F55F75 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D7B1EA245A2D3BB23458EC800AF8B9C7 /* Pods-ColorPicker.release.xcconfig */; + baseConfigurationReference = 99D1B4DCE4A3C86EC4EB1DA00865E9B1 /* Eureka.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -692,110 +693,62 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/Pods-ColorPicker/Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Eureka/Eureka-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Eureka/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-ColorPicker/Pods-ColorPicker.modulemap"; + MODULEMAP_FILE = "Target Support Files/Eureka/Eureka.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = Pods_ColorPicker; + PRODUCT_NAME = Eureka; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; - 643C76AA582046977B7877822ED7A258 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGNING_REQUIRED = NO; - COPY_PHASE_STRIP = NO; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_DEBUG=1", - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - ONLY_ACTIVE_ARCH = YES; - PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; - STRIP_INSTALLED_PRODUCT = NO; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Debug; - }; - 6B592F4CC267508DF09A643202257058 /* Debug */ = { + 622A647E88DD596D9378067D994EF4DD /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F930180A7601440DC45A7552C98ED6A9 /* UIColor_Hex_Swift.xcconfig */; + baseConfigurationReference = D7B1EA245A2D3BB23458EC800AF8B9C7 /* Pods-ColorPicker.release.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/UIColor_Hex_Swift/UIColor_Hex_Swift-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/UIColor_Hex_Swift/Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-ColorPicker/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/UIColor_Hex_Swift/UIColor_Hex_Swift.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = UIColor_Hex_Swift; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-ColorPicker/Pods-ColorPicker.modulemap"; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Pods_ColorPicker; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; 92D5C5CCA22C68D26A4933F74470D038 /* Debug */ = { isa = XCBuildConfiguration; @@ -836,38 +789,52 @@ }; name = Debug; }; - AE88C678AEE4C2372629E0A23239EECF /* Debug */ = { + 9BFC9E4A7AAD7A607ACE06D95A401A5A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 99D1B4DCE4A3C86EC4EB1DA00865E9B1 /* Eureka.xcconfig */; buildSettings = { - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Eureka/Eureka-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Eureka/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Eureka/Eureka.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Eureka; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = NO; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + ONLY_ACTIVE_ARCH = YES; + PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; + STRIP_INSTALLED_PRODUCT = NO; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; + SYMROOT = "${SRCROOT}/../build"; }; name = Debug; }; @@ -915,7 +882,42 @@ }; name = Release; }; - D46BD71F55A5058116376C24D476C855 /* Release */ = { + C5C2EE08CD8ABC2C0E6A80832A4EF7BA /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F930180A7601440DC45A7552C98ED6A9 /* UIColor_Hex_Swift.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREFIX_HEADER = "Target Support Files/UIColor_Hex_Swift/UIColor_Hex_Swift-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/UIColor_Hex_Swift/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/UIColor_Hex_Swift/UIColor_Hex_Swift.modulemap"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_NAME = UIColor_Hex_Swift; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + D2DB219A0CD5D0BFF1867CBC3F24018B /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 99D1B4DCE4A3C86EC4EB1DA00865E9B1 /* Eureka.xcconfig */; buildSettings = { @@ -924,7 +926,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -937,17 +939,18 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/Eureka/Eureka.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; + MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = Eureka; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; /* End XCBuildConfiguration section */ @@ -955,7 +958,7 @@ 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - 643C76AA582046977B7877822ED7A258 /* Debug */, + 9BFC9E4A7AAD7A607ACE06D95A401A5A /* Debug */, C03B8870130C98D1B02B59D003687524 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -964,8 +967,8 @@ 50C8E1EFA0C5DC6AD96DBEE0EFA14308 /* Build configuration list for PBXNativeTarget "Eureka" */ = { isa = XCConfigurationList; buildConfigurations = ( - AE88C678AEE4C2372629E0A23239EECF /* Debug */, - D46BD71F55A5058116376C24D476C855 /* Release */, + D2DB219A0CD5D0BFF1867CBC3F24018B /* Debug */, + 2F5EB86BB29399CECCB7751986F55F75 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -973,8 +976,8 @@ A8D87D552957E2612297521714A21E63 /* Build configuration list for PBXNativeTarget "UIColor_Hex_Swift" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6B592F4CC267508DF09A643202257058 /* Debug */, - 4F46456883363212A9C9A60C24F1A42F /* Release */, + C5C2EE08CD8ABC2C0E6A80832A4EF7BA /* Debug */, + 03EB0770382FA058DE3E27FDEDF37AE6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Pods/Target Support Files/Eureka/Info.plist b/Pods/Target Support Files/Eureka/Info.plist index 4522675..3424ca6 100644 --- a/Pods/Target Support Files/Eureka/Info.plist +++ b/Pods/Target Support Files/Eureka/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.0.0 + 4.0.0 CFBundleSignature ???? CFBundleVersion diff --git a/Pods/Target Support Files/Pods-ColorPicker/Pods-ColorPicker-frameworks.sh b/Pods/Target Support Files/Pods-ColorPicker/Pods-ColorPicker-frameworks.sh index 6ef68d1..1dd040d 100755 --- a/Pods/Target Support Files/Pods-ColorPicker/Pods-ColorPicker-frameworks.sh +++ b/Pods/Target Support Files/Pods-ColorPicker/Pods-ColorPicker-frameworks.sh @@ -6,6 +6,10 @@ mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + install_framework() { if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then @@ -23,9 +27,9 @@ install_framework() source="$(readlink "${source}")" fi - # use filter instead of exclude so missing patterns dont' throw errors - echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" - rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" local basename basename="$(basename -s .framework "$1")" @@ -54,6 +58,15 @@ install_framework() fi } +# Copies the dSYM of a vendored framework +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}" + fi +} + # Signs a framework with the provided identity code_sign_if_enabled() { if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then @@ -76,7 +89,7 @@ strip_invalid_archs() { archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" stripped="" for arch in $archs; do - if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then + if ! [[ "${ARCHS}" == *"$arch"* ]]; then # Strip non-valid architectures in-place lipo -remove "$arch" -output "$binary" "$binary" || exit 1 stripped="$stripped $arch" @@ -89,12 +102,12 @@ strip_invalid_archs() { if [[ "$CONFIGURATION" == "Debug" ]]; then - install_framework "$BUILT_PRODUCTS_DIR/Eureka/Eureka.framework" - install_framework "$BUILT_PRODUCTS_DIR/UIColor_Hex_Swift/UIColor_Hex_Swift.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Eureka/Eureka.framework" + install_framework "${BUILT_PRODUCTS_DIR}/UIColor_Hex_Swift/UIColor_Hex_Swift.framework" fi if [[ "$CONFIGURATION" == "Release" ]]; then - install_framework "$BUILT_PRODUCTS_DIR/Eureka/Eureka.framework" - install_framework "$BUILT_PRODUCTS_DIR/UIColor_Hex_Swift/UIColor_Hex_Swift.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Eureka/Eureka.framework" + install_framework "${BUILT_PRODUCTS_DIR}/UIColor_Hex_Swift/UIColor_Hex_Swift.framework" fi if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then wait diff --git a/Pods/Target Support Files/Pods-ColorPicker/Pods-ColorPicker-resources.sh b/Pods/Target Support Files/Pods-ColorPicker/Pods-ColorPicker-resources.sh index aed060f..a7df440 100755 --- a/Pods/Target Support Files/Pods-ColorPicker/Pods-ColorPicker-resources.sh +++ b/Pods/Target Support Files/Pods-ColorPicker/Pods-ColorPicker-resources.sh @@ -8,6 +8,10 @@ RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt XCASSET_FILES=() +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + case "${TARGETED_DEVICE_FAMILY}" in 1,2) TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" @@ -44,29 +48,29 @@ EOM fi case $RESOURCE_PATH in *.storyboard) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} ;; *.xib) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} ;; *.framework) - echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" ;; *.xcdatamodel) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" ;; *.xcdatamodeld) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" ;; *.xcmappingmodel) - echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" ;; *.xcassets) @@ -74,7 +78,7 @@ EOM XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") ;; *) - echo "$RESOURCE_PATH" + echo "$RESOURCE_PATH" || true echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" ;; esac diff --git a/README.md b/README.md index 4449287..8d02f68 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ If you use **ColorPickerRow** in your app I would love to hear about it! Drop me ~~~~ pod 'ColorPickerRow', :git => 'https://github.com/EurekaCommunity/ColorPickerRow' - pod 'UIColor_Hex_Swift', '~> 3.0.2' + pod 'UIColor_Hex_Swift' ~~~~ 2. Run `$ pod install`