Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swift 4 swipeable #1249

Closed
wants to merge 12 commits into from
4 changes: 4 additions & 0 deletions Eureka.xcodeproj/project.pbxproj
Expand Up @@ -83,6 +83,7 @@
49ADC7F91C8A83240073952B /* StepperRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49ADC7F81C8A83240073952B /* StepperRow.swift */; };
51729DF61B9A4F5E004A00EB /* Eureka.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51729DEB1B9A4F5E004A00EB /* Eureka.framework */; };
51729E671B9A5FA5004A00EB /* Eureka.h in Headers */ = {isa = PBXBuildFile; fileRef = 51729E661B9A5FA5004A00EB /* Eureka.h */; settings = {ATTRIBUTES = (Public, ); }; };
798C5ADA1EF1E35600A21F52 /* SwipeActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 798C5AD91EF1E35600A21F52 /* SwipeActions.swift */; };
8690E4BE1CFDE062004CDB1C /* Eureka.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 8690E4BD1CFDE062004CDB1C /* Eureka.bundle */; };
B257FE2E1EC0F66900043911 /* RowsInsertionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B257FE2D1EC0F66900043911 /* RowsInsertionTests.swift */; };
B2A401161EC0BA140042EDF0 /* SectionsInsertionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2A401151EC0BA140042EDF0 /* SectionsInsertionTests.swift */; };
Expand Down Expand Up @@ -179,6 +180,7 @@
51729DF51B9A4F5E004A00EB /* EurekaTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EurekaTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
51729DFC1B9A4F5E004A00EB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Tests/Info.plist; sourceTree = "<group>"; };
51729E661B9A5FA5004A00EB /* Eureka.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Eureka.h; path = Source/Eureka.h; sourceTree = SOURCE_ROOT; };
798C5AD91EF1E35600A21F52 /* SwipeActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeActions.swift; sourceTree = "<group>"; };
8690E4BD1CFDE062004CDB1C /* Eureka.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Eureka.bundle; sourceTree = "<group>"; };
B257FE2D1EC0F66900043911 /* RowsInsertionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RowsInsertionTests.swift; path = Tests/RowsInsertionTests.swift; sourceTree = SOURCE_ROOT; };
B2A401151EC0BA140042EDF0 /* SectionsInsertionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SectionsInsertionTests.swift; path = Tests/SectionsInsertionTests.swift; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -225,6 +227,7 @@
28EEBFF71C7E241200300699 /* SelectableRowType.swift */,
2859CDBF1C7D138D0002982F /* Section.swift */,
2859CE231C7E141B0002982F /* SelectableSection.swift */,
798C5AD91EF1E35600A21F52 /* SwipeActions.swift */,
28EE0FDD1D5E889F00B91340 /* Validation.swift */,
);
name = Core;
Expand Down Expand Up @@ -530,6 +533,7 @@
49ADC7F91C8A83240073952B /* StepperRow.swift in Sources */,
28EE46AC1C7F712300EFF4A2 /* DateInlineRow.swift in Sources */,
28EEC01C1C7E3A7400300699 /* ButtonRowWithPresent.swift in Sources */,
798C5ADA1EF1E35600A21F52 /* SwipeActions.swift in Sources */,
28EEBFF41C7E240000300699 /* RowProtocols.swift in Sources */,
28EEBFFE1C7E281F00300699 /* CheckRow.swift in Sources */,
2859CDC41C7D19C50002982F /* HeaderFooterView.swift in Sources */,
Expand Down
20 changes: 20 additions & 0 deletions Example/Example/Base.lproj/Main.storyboard
Expand Up @@ -172,6 +172,7 @@
<segue destination="1By-iT-GXN" kind="push" identifier="ValidationsControllerSegue" id="e8a-Jy-4iL"/>
<segue destination="1Eh-Nv-AVS" kind="push" identifier="CustomDesignControllerSegue" id="qm6-xE-x5d"/>
<segue destination="qIY-1j-dNf" kind="push" identifier="MultivaluedSectionsControllerSegue" id="HjC-JK-Qvc"/>
<segue destination="fc5-sQ-cEm" kind="push" identifier="SwipeActionsControllerSegue" id="AxK-me-pi6"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Eoz-Jq-Zy9" userLabel="First Responder" sceneMemberID="firstResponder"/>
Expand Down Expand Up @@ -264,6 +265,25 @@
</objects>
<point key="canvasLocation" x="463" y="1077"/>
</scene>
<!--SwipeActions Example-->
<scene sceneID="h0m-5n-GTL">
<objects>
<viewController title="SwipeActions Example" id="fc5-sQ-cEm" customClass="SwipeActionsController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="ImV-ow-JvS"/>
<viewControllerLayoutGuide type="bottom" id="3OX-ei-O2d"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="BDe-QW-0vU">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
<navigationItem key="navigationItem" id="KY1-r2-ar2"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="axy-1K-pFt" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-530" y="1833"/>
</scene>
<!--Multivalued Sections Example-->
<scene sceneID="zbo-bQ-HRw">
<objects>
Expand Down
72 changes: 63 additions & 9 deletions Example/Example/ViewController.swift
Expand Up @@ -106,15 +106,11 @@ class HomeViewController : FormViewController {
row.title = row.tag
row.presentationMode = .segueName(segueName: "MultivaluedSectionsControllerSegue", onDismiss: nil)
}


+++ Section()
<<< ButtonRow() { (row: ButtonRow) -> Void in
row.title = "About"
}
.onCellSelection { [weak self] (cell, row) in
self?.showAlert()
}

<<< ButtonRow("Swipe Actions") { (row: ButtonRow) -> Void in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the same indentation that is used in the whole project (4 spaces)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

row.title = row.tag
row.presentationMode = .segueName(segueName: "SwipeActionsControllerSegue", onDismiss: nil)
}
}


Expand Down Expand Up @@ -1747,6 +1743,64 @@ class MultivaluedOnlyDeleteController: FormViewController {
}
}

class SwipeActionsController: FormViewController {

override func viewDidLoad() {
super.viewDidLoad()

form +++ Section(footer: "Eureka sets table.isEditing = false for SwipeActions.\n\nMultivaluedSections need table.isEditing = true, therefore both can't be used on the same view.")
<<< LabelRow("Actions Right: iOS >= 7"){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please always keep a white space before an opening curly brace

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

$0.title = $0.tag

$0.trailingSwipeConfiguration = SwipeConfiguration(){
let moreAction = SwipeAction(style: .normal, title: "More", handler: { (action, path, completionHandler) in
print("More")
completionHandler?(true)
})

let deleteAction = SwipeAction(style: .destructive, title: "Delete", handler: { (action, path, completionHandler) in
print("Delete")
completionHandler?(true)
})

$0.actions = [deleteAction,moreAction]
}
}

<<< LabelRow("Actions Left & Right: iOS >= 11"){
$0.title = $0.tag

$0.trailingSwipeConfiguration = SwipeConfiguration(){
let moreAction = SwipeAction(style: .normal, title: "More", handler: { (action, path, completionHandler) in
print("More")
completionHandler?(true)
})

let deleteAction = SwipeAction(style: .destructive, title: "Delete", handler: { (action, path, completionHandler) in
print("Delete")
completionHandler?(true)
})

$0.performsFirstActionWithFullSwipe = true
$0.actions = [deleteAction,moreAction]
}

if #available(iOS 11,*){
$0.leadingSwipeConfiguration = SwipeConfiguration(){
let infoAction = SwipeAction(style: .normal, title: "Info", handler: { (action, path, completionHandler) in
print("Info")
completionHandler?(true)
})
infoAction.backgroundColor = .blue

$0.performsFirstActionWithFullSwipe = true
$0.actions = [infoAction]
}
}
}
}
}

class EurekaLogoViewNib: UIView {

@IBOutlet weak var imageView: UIImageView!
Expand Down
13 changes: 12 additions & 1 deletion Source/Core/BaseRow.swift
Expand Up @@ -98,7 +98,18 @@ open class BaseRow: BaseRowType {
public var isHidden: Bool { return hiddenCache }

/// The section to which this row belongs.
public weak var section: Section?
open weak var section: Section?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this change does not seem to be needed? Please revert it back

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Done.


public var trailingSwipeConfiguration: SwipeConfiguration?

//needs the accessor because if marked directly this throws "Stored properties cannot be marked potentially unavailable with '@available'"
private var _leadingSwipeConfiguration: SwipeConfiguration?

@available(iOS 11,*)
public var leadingSwipeConfiguration: SwipeConfiguration?{
get{ return self._leadingSwipeConfiguration }
set{ self._leadingSwipeConfiguration = newValue }
}

public required init(tag: String? = nil) {
self.tag = tag
Expand Down
40 changes: 32 additions & 8 deletions Source/Core/Core.swift
Expand Up @@ -462,9 +462,7 @@ open class FormViewController: UIViewController, FormViewControllerProtocol, For
tableView.dataSource = self
}
tableView.estimatedRowHeight = BaseRow.estimatedRowHeight

tableView.setEditing(true, animated: false)
tableView.allowsSelectionDuringEditing = true
tableView.allowsSelectionDuringEditing = true
}

open override func viewWillAppear(_ animated: Bool) {
Expand Down Expand Up @@ -502,6 +500,10 @@ open class FormViewController: UIViewController, FormViewControllerProtocol, For

NotificationCenter.default.addObserver(self, selector: #selector(FormViewController.keyboardWillShow(_:)), name: Notification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(FormViewController.keyboardWillHide(_:)), name: Notification.Name.UIKeyboardWillHide, object: nil)

if form.containsMultivaluedSection{
tableView.setEditing(true, animated: false)
}
}

open override func viewWillDisappear(_ animated: Bool) {
Expand Down Expand Up @@ -789,8 +791,13 @@ extension FormViewController : UITableViewDelegate {
}

open func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
guard let section = form[indexPath.section] as? MultivaluedSection else { return false }
let row = form[indexPath]
let row = form[indexPath]
if let actions = row.trailingSwipeConfiguration?.actions.count, actions > 0{
return true
} else if #available(iOS 11,*), let actions = row.leadingSwipeConfiguration?.actions.count, actions > 0{
return true
}
guard let section = form[indexPath.section] as? MultivaluedSection else { return false }
guard !row.isDisabled else { return false }
guard !(indexPath.row == section.count - 1 && section.multivaluedOptions.contains(.Insert) && section.showInsertIconInAddButton) else {
return true
Expand Down Expand Up @@ -849,12 +856,12 @@ extension FormViewController : UITableViewDelegate {
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 }

let destRow = form[proposedDestinationIndexPath]
if destRow is BaseInlineRowType && destRow._inlineRow != nil {
return IndexPath(row: proposedDestinationIndexPath.row + (sourceIndexPath.row < proposedDestinationIndexPath.row ? 1 : -1), section:sourceIndexPath.section)
}

if proposedDestinationIndexPath.row > 0 {
let previousRow = form[IndexPath(row: proposedDestinationIndexPath.row - 1, section: proposedDestinationIndexPath.section)]
if previousRow is BaseInlineRowType && previousRow._inlineRow != nil {
Expand All @@ -871,7 +878,7 @@ extension FormViewController : UITableViewDelegate {

guard var section = form[sourceIndexPath.section] as? MultivaluedSection else { return }
if sourceIndexPath.row < section.count && destinationIndexPath.row < section.count && sourceIndexPath.row != destinationIndexPath.row {

let sourceRow = form[sourceIndexPath]
animateTableView = false
section.remove(at: sourceIndexPath.row)
Expand All @@ -884,6 +891,9 @@ extension FormViewController : UITableViewDelegate {

open func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
guard let section = form[indexPath.section] as? MultivaluedSection else {
if let actions = form[indexPath].trailingSwipeConfiguration?.actions.count, actions > 0{
return .delete
}
return .none
}
if section.multivaluedOptions.contains(.Insert) && indexPath.row == section.count - 1 {
Expand All @@ -898,6 +908,20 @@ extension FormViewController : UITableViewDelegate {
open func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return self.tableView(tableView, editingStyleForRowAt: indexPath) != .none
}

@available(iOS 11,*)
public func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return form[indexPath].leadingSwipeConfiguration?.platformValue as? UISwipeActionsConfiguration
}

@available(iOS 11,*)
public func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
return form[indexPath].trailingSwipeConfiguration?.platformValue as? UISwipeActionsConfiguration
}

public func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?{
return form[indexPath].trailingSwipeConfiguration?.platformActions as? [UITableViewRowAction]
}
}

extension FormViewController : UITableViewDataSource {
Expand Down
6 changes: 6 additions & 0 deletions Source/Core/Form.swift
Expand Up @@ -352,6 +352,12 @@ extension Form {
}
kvoWrapper.sections.insert(section, at: formIndex == NSNotFound ? 0 : formIndex + 1 )
}

var containsMultivaluedSection: Bool{
return kvoWrapper.sections.contains { (section) -> Bool in
return section is MultivaluedSection
}
}

func getValues(for rows: [BaseRow]) -> [String: Any?] {
return rows.reduce([String: Any?]()) {
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Section.swift
Expand Up @@ -455,7 +455,7 @@ open class MultivaluedSection: Section {
let addRow = addButtonProvider(self)
addRow.onCellSelection { cell, row in
guard let tableView = cell.formViewController()?.tableView, let indexPath = row.indexPath else { return }
cell.formViewController()?.tableView(tableView, commit: .insert, forRowAt: indexPath)
cell.formViewController()?.tableView(tableView, commit: .insert, forRowAt: indexPath)
}
self <<< addRow
}
Expand Down
4 changes: 3 additions & 1 deletion Source/Core/SelectableSection.swift
Expand Up @@ -84,7 +84,9 @@ extension SelectableSectionType where Self: Section {
for row in rows {
if let row = row as? SelectableRow {
row.onCellSelection { [weak self] cell, row in
guard let s = self, !row.isDisabled else { return }
guard let s = self, !row.isDisabled else {
return
}
switch s.selectionType {
case .multipleSelection:
row.value = row.value == nil ? row.selectableValue : nil
Expand Down