ActionHandler approach
This commit is contained in:
parent
9c3a1ee5c9
commit
f8c659f069
|
|
@ -21,17 +21,29 @@
|
|||
import UIKit
|
||||
import Foundation
|
||||
|
||||
internal enum ActionHandler<T, E> {
|
||||
|
||||
case actionBlock((data: ActionData<T, E>) -> Void)
|
||||
case actionReturnBlock((data: ActionData<T, E>) -> AnyObject)
|
||||
|
||||
func call(data: ActionData<T, E>) -> AnyObject {
|
||||
|
||||
switch (self) {
|
||||
case .actionBlock(let closure):
|
||||
closure(data: data)
|
||||
return true
|
||||
case .actionReturnBlock(let closure):
|
||||
return closure(data: data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Responsible for building cells of given type and passing items to them.
|
||||
*/
|
||||
public class TableRowBuilder<I, C where C: UITableViewCell> : RowBuilder {
|
||||
|
||||
public typealias ReturnValue = AnyObject
|
||||
|
||||
public typealias TableRowBuilderActionBlock = (data: ActionData<I, C>) -> Void
|
||||
public typealias TableRowBuilderReturnValueActionBlock = (data: ActionData<I, C>) -> ReturnValue
|
||||
|
||||
private var actions = Dictionary<String, TableRowBuilderActionBlock>()
|
||||
|
||||
private var actions = Dictionary<String, ActionHandler<I, C>>()
|
||||
private var items = [I]()
|
||||
|
||||
public var reusableIdentifier: String
|
||||
|
|
@ -67,36 +79,33 @@ public class TableRowBuilder<I, C where C: UITableViewCell> : RowBuilder {
|
|||
}
|
||||
|
||||
// MARK: Chaining actions
|
||||
|
||||
public func action(key: String, action: TableRowBuilderActionBlock) -> Self {
|
||||
|
||||
actions[key] = action
|
||||
|
||||
public func action(key: String, action: (data: ActionData<I, C>) -> Void) -> Self {
|
||||
|
||||
actions[key] = .actionBlock(action)
|
||||
return self
|
||||
}
|
||||
|
||||
public func action(key: ActionType, action: TableRowBuilderActionBlock) -> Self {
|
||||
|
||||
actions[key.rawValue] = action
|
||||
public func action(key: ActionType, action: (data: ActionData<I, C>) -> Void) -> Self {
|
||||
|
||||
actions[key.rawValue] = .actionBlock(action)
|
||||
return self
|
||||
}
|
||||
|
||||
public func action(key: ActionType, action: TableRowBuilderReturnValueActionBlock) -> Self {
|
||||
|
||||
|
||||
public func action(key: ActionType, action: (data: ActionData<I, C>) -> AnyObject) -> Self {
|
||||
|
||||
actions[key.rawValue] = .actionReturnBlock(action)
|
||||
return self
|
||||
}
|
||||
|
||||
// MARK: Triggers
|
||||
|
||||
public func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> ActionResult {
|
||||
|
||||
let actionData = ActionData(cell: cell as! C, indexPath: indexPath, item: items[itemIndex], itemIndex: itemIndex)
|
||||
|
||||
if let block = actions[key] {
|
||||
block(data: actionData)
|
||||
return .Failure
|
||||
public func triggerAction(key: String, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? {
|
||||
|
||||
if let action = actions[key] {
|
||||
return action.call(ActionData(cell: cell as? C, indexPath: indexPath, item: items[itemIndex], itemIndex: itemIndex))
|
||||
}
|
||||
return .Failure
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,10 +121,10 @@ public class TableConfigurableRowBuilder<I, C: ConfigurableCell where C.Item ==
|
|||
public init(items: [I]? = nil) {
|
||||
super.init(items: items, id: C.reusableIdentifier())
|
||||
}
|
||||
|
||||
public override func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> ActionResult {
|
||||
|
||||
public override func triggerAction(key: String, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? {
|
||||
|
||||
(cell as! C).configureWithItem(items[itemIndex])
|
||||
(cell as? C)?.configureWithItem(items[itemIndex])
|
||||
|
||||
return super.triggerAction(key, cell: cell, indexPath: indexPath, itemIndex: itemIndex)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,12 +39,12 @@ public enum ActionType : String {
|
|||
|
||||
public struct ActionData<I, C> {
|
||||
|
||||
public let cell: C
|
||||
public let cell: C?
|
||||
public let item: I
|
||||
public let itemIndex: Int
|
||||
public let indexPath: NSIndexPath
|
||||
|
||||
init(cell: C, indexPath: NSIndexPath, item: I, itemIndex: Int) {
|
||||
init(cell: C?, indexPath: NSIndexPath, item: I, itemIndex: Int) {
|
||||
|
||||
self.cell = cell
|
||||
self.indexPath = indexPath
|
||||
|
|
@ -53,31 +53,6 @@ public struct ActionData<I, C> {
|
|||
}
|
||||
}
|
||||
|
||||
public enum ActionResult {
|
||||
|
||||
case Success(returnValue: AnyObject)
|
||||
case Failure
|
||||
|
||||
/// Returns true if the result is a success, false otherwise.
|
||||
public var isSuccess: Bool {
|
||||
switch self {
|
||||
case .Success:
|
||||
return true
|
||||
case .Failure:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public var returnValue: AnyObject? {
|
||||
switch self {
|
||||
case .Success(let returnValue):
|
||||
return returnValue
|
||||
case .Failure:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
A custom action that you can trigger from your cell.
|
||||
You can eacily catch actions using a chaining manner with your row builder.
|
||||
|
|
@ -127,10 +102,9 @@ public protocol RowBuilder {
|
|||
var numberOfRows: Int { get }
|
||||
var reusableIdentifier: String { get }
|
||||
|
||||
func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> ActionResult
|
||||
func triggerAction(key: String, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject?
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Responsible for table view's datasource and delegate.
|
||||
*/
|
||||
|
|
@ -179,17 +153,12 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
return sections[indexPath.section].builderAtIndex(indexPath.row)!
|
||||
}
|
||||
|
||||
private func triggerAction(action: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath) -> ActionResult {
|
||||
private func triggerAction(action: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath) -> AnyObject? {
|
||||
|
||||
let builder = builderAtIndexPath(indexPath)
|
||||
return builder.0.triggerAction(action.rawValue, cell: cell!, indexPath: indexPath, itemIndex: builder.1)
|
||||
return builder.0.triggerAction(action.rawValue, cell: cell, indexPath: indexPath, itemIndex: builder.1)
|
||||
}
|
||||
|
||||
private func trigger() -> AnyObject {
|
||||
|
||||
return 100
|
||||
}
|
||||
|
||||
internal func didReceiveAction(notification: NSNotification) {
|
||||
|
||||
if let action = notification.object as? Action, indexPath = tableView.indexPathForCell(action.cell) {
|
||||
|
|
@ -262,7 +231,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
|
||||
let cell = tableView.cellForRowAtIndexPath(indexPath)
|
||||
|
||||
if triggerAction(.click, cell: cell, indexPath: indexPath).isSuccess {
|
||||
if triggerAction(.click, cell: cell, indexPath: indexPath) != nil {
|
||||
tableView.deselectRowAtIndexPath(indexPath, animated: true)
|
||||
} else {
|
||||
triggerAction(.select, cell: cell, indexPath: indexPath)
|
||||
|
|
@ -281,11 +250,11 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
|
||||
public func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool {
|
||||
|
||||
return triggerAction(.shouldHighlight, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath).returnValue as? Bool ?? true
|
||||
return triggerAction(.shouldHighlight, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? Bool ?? true
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
|
||||
|
||||
return triggerAction(.height, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath).returnValue as? CGFloat ?? tableView.rowHeight
|
||||
return triggerAction(.height, cell: nil, indexPath: indexPath) as? CGFloat ?? tableView.rowHeight
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
|
@ -19,22 +19,28 @@ class ViewController: UIViewController {
|
|||
tableDirector = TableDirector(tableView: tableView)
|
||||
|
||||
let rowBuilder = TableRowBuilder<Int, UITableViewCell>(items: [1, 2, 3, 4], id: "cell")
|
||||
.action(.configure) { data in
|
||||
.action(.configure) { data -> Void in
|
||||
|
||||
data.cell.textLabel?.text = "\(data.item)"
|
||||
data.cell?.textLabel?.text = "\(data.item)"
|
||||
}
|
||||
.action(.shouldHighlight) { _ in
|
||||
.action(.height) { data in
|
||||
|
||||
return 50
|
||||
}
|
||||
.action(.shouldHighlight) { data in
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
let configurableRowBuilder = TableConfigurableRowBuilder<String, ConfigurableTableViewCell>(items: ["5", "6", "7", "8"])
|
||||
.action(kConfigurableTableViewCellButtonClickedAction) { data in
|
||||
.action(kConfigurableTableViewCellButtonClickedAction) { data -> Void in
|
||||
|
||||
print("custom action indexPath: \(data.indexPath), item: \(data.item)")
|
||||
}
|
||||
.action(.click) { data in
|
||||
|
||||
.action(.click) { data -> Void in
|
||||
|
||||
data.cell!.textLabel?.text = ""
|
||||
|
||||
print("custom action indexPath: \(data.indexPath), item: \(data.item)")
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue