From 73ea2cf5730f055a3c1f474f149b1de6e51607b5 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Fri, 13 Nov 2015 01:24:24 +0300 Subject: [PATCH] added TableDirector file --- Tablet/TableDirector.swift | 176 ++++++++++++++++++ Tablet/TableSectionBuilder.swift | 1 + Tablet/Tablet.swift | 154 --------------- .../TabletDemo.xcodeproj/project.pbxproj | 14 +- .../UserInterfaceState.xcuserstate | Bin 19550 -> 19785 bytes TabletDemo/TabletDemo/ViewController.swift | 12 +- 6 files changed, 192 insertions(+), 165 deletions(-) create mode 100644 Tablet/TableDirector.swift diff --git a/Tablet/TableDirector.swift b/Tablet/TableDirector.swift new file mode 100644 index 0000000..5e81f42 --- /dev/null +++ b/Tablet/TableDirector.swift @@ -0,0 +1,176 @@ +// +// Copyright (c) 2015 Max Sokolov https://twitter.com/max_sokolov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import UIKit +import Foundation + +/** + Responsible for table view's datasource and delegate. + */ +public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate { + + private weak var tableView: UITableView! + private var sections = [TableSectionBuilder]() + + public init(tableView: UITableView) { + super.init() + + self.tableView = tableView + self.tableView.delegate = self + self.tableView.dataSource = self + + NSNotificationCenter.defaultCenter().addObserver(self, selector: "didReceiveAction:", name: kActionPerformedNotificationKey, object: nil) + } + + deinit { + + NSNotificationCenter.defaultCenter().removeObserver(self) + } + + // MARK: Public methods + + public func appendSection(section: TableSectionBuilder) { + sections.append(section) + } + + public func appendSections(sections: [TableSectionBuilder]) { + self.sections.appendContentsOf(sections) + } + + // MARK: Private methods + + /** + Find a row builder that responsible for building a row from cell with given item type. + + - Parameters: + - indexPath: path of cell to dequeue + + - Returns: A touple - (builder, builderItemIndex) + */ + private func builderAtIndexPath(indexPath: NSIndexPath) -> (RowBuilder, Int) { + + return sections[indexPath.section].builderAtIndex(indexPath.row)! + } + + 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) + } + + internal func didReceiveAction(notification: NSNotification) { + + if let action = notification.object as? Action, indexPath = tableView.indexPathForCell(action.cell) { + + let builder = builderAtIndexPath(indexPath) + builder.0.triggerAction(action.key, cell: action.cell, indexPath: indexPath, itemIndex: builder.1) + } + } + + // MARK: UITableViewDataSource - configuration + + public func numberOfSectionsInTableView(tableView: UITableView) -> Int { + + return sections.count + } + + public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + + return sections[section].numberOfRowsInSection + } + + public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + + let builder = builderAtIndexPath(indexPath) + + let cell = tableView.dequeueReusableCellWithIdentifier(builder.0.reusableIdentifier, forIndexPath: indexPath) + + builder.0.triggerAction(ActionType.configure.rawValue, cell: cell, indexPath: indexPath, itemIndex: builder.1) + + return cell + } + + // MARK: UITableViewDataSource - section setup + + public func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + + return sections[section].headerTitle + } + + public func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String? { + + return sections[section].footerTitle + } + + // MARK: UITableViewDelegate - section setup + + public func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + + return sections[section].headerView + } + + public func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + + return sections[section].footerView + } + + public func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + + return sections[section].headerHeight + } + + public func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + + return sections[section].footerHeight + } + + // MARK: UITableViewDelegate - actions + + public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + + let cell = tableView.cellForRowAtIndexPath(indexPath) + + if triggerAction(.click, cell: cell, indexPath: indexPath) != nil { + tableView.deselectRowAtIndexPath(indexPath, animated: true) + } else { + triggerAction(.select, cell: cell, indexPath: indexPath) + } + } + + public func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) { + + triggerAction(.deselect, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) + } + + public func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { + + triggerAction(.willDisplay, cell: cell, indexPath: indexPath) + } + + public func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool { + + 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: nil, indexPath: indexPath) as? CGFloat ?? tableView.rowHeight + } +} \ No newline at end of file diff --git a/Tablet/TableSectionBuilder.swift b/Tablet/TableSectionBuilder.swift index ac58e38..4853b3e 100644 --- a/Tablet/TableSectionBuilder.swift +++ b/Tablet/TableSectionBuilder.swift @@ -23,6 +23,7 @@ import Foundation /** Responsible for building a certain table view section. + Can host several row builders. */ public class TableSectionBuilder { diff --git a/Tablet/Tablet.swift b/Tablet/Tablet.swift index 00035e0..d9fbf9e 100644 --- a/Tablet/Tablet.swift +++ b/Tablet/Tablet.swift @@ -103,158 +103,4 @@ public protocol RowBuilder { var reusableIdentifier: String { get } func triggerAction(key: String, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? -} - -/** - Responsible for table view's datasource and delegate. -*/ -public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate { - - private weak var tableView: UITableView! - private var sections = [TableSectionBuilder]() - - public init(tableView: UITableView) { - super.init() - - self.tableView = tableView - self.tableView.delegate = self - self.tableView.dataSource = self - - NSNotificationCenter.defaultCenter().addObserver(self, selector: "didReceiveAction:", name: kActionPerformedNotificationKey, object: nil) - } - - deinit { - - NSNotificationCenter.defaultCenter().removeObserver(self) - } - - // MARK: Public methods - - public func appendSection(section: TableSectionBuilder) { - sections.append(section) - } - - public func appendSections(sections: [TableSectionBuilder]) { - self.sections.appendContentsOf(sections) - } - - // MARK: Private methods - - /** - Find a row builder that responsible for building a row from cell with given item type. - - - Parameters: - - indexPath: path of cell to dequeue - - - Returns: A touple - (builder, builderItemIndex) - */ - private func builderAtIndexPath(indexPath: NSIndexPath) -> (RowBuilder, Int) { - - return sections[indexPath.section].builderAtIndex(indexPath.row)! - } - - 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) - } - - internal func didReceiveAction(notification: NSNotification) { - - if let action = notification.object as? Action, indexPath = tableView.indexPathForCell(action.cell) { - - let builder = builderAtIndexPath(indexPath) - builder.0.triggerAction(action.key, cell: action.cell, indexPath: indexPath, itemIndex: builder.1) - } - } - - // MARK: UITableViewDataSource - configuration - - public func numberOfSectionsInTableView(tableView: UITableView) -> Int { - - return sections.count - } - - public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - - return sections[section].numberOfRowsInSection - } - - public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { - - let builder = builderAtIndexPath(indexPath) - - let cell = tableView.dequeueReusableCellWithIdentifier(builder.0.reusableIdentifier, forIndexPath: indexPath) - - builder.0.triggerAction(ActionType.configure.rawValue, cell: cell, indexPath: indexPath, itemIndex: builder.1) - - return cell - } - - // MARK: UITableViewDataSource - section setup - - public func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - - return sections[section].headerTitle - } - - public func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String? { - - return sections[section].footerTitle - } - - // MARK: UITableViewDelegate - section setup - - public func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - - return sections[section].headerView - } - - public func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { - - return sections[section].footerView - } - - public func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - - return sections[section].headerHeight - } - - public func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { - - return sections[section].footerHeight - } - - // MARK: UITableViewDelegate - actions - - public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { - - let cell = tableView.cellForRowAtIndexPath(indexPath) - - if triggerAction(.click, cell: cell, indexPath: indexPath) != nil { - tableView.deselectRowAtIndexPath(indexPath, animated: true) - } else { - triggerAction(.select, cell: cell, indexPath: indexPath) - } - } - - public func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) { - - triggerAction(.deselect, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) - } - - public func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { - - triggerAction(.willDisplay, cell: cell, indexPath: indexPath) - } - - public func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool { - - 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: nil, indexPath: indexPath) as? CGFloat ?? tableView.rowHeight - } } \ No newline at end of file diff --git a/TabletDemo/TabletDemo.xcodeproj/project.pbxproj b/TabletDemo/TabletDemo.xcodeproj/project.pbxproj index 9f09f6c..42969fb 100644 --- a/TabletDemo/TabletDemo.xcodeproj/project.pbxproj +++ b/TabletDemo/TabletDemo.xcodeproj/project.pbxproj @@ -7,20 +7,22 @@ objects = { /* Begin PBXBuildFile section */ - 508B71841BF48DD300272920 /* TableSectionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508B71831BF48DD300272920 /* TableSectionBuilder.swift */; settings = {ASSET_TAGS = (); }; }; - 508B71861BF48E0D00272920 /* TableRowBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508B71851BF48E0D00272920 /* TableRowBuilder.swift */; settings = {ASSET_TAGS = (); }; }; + 508B71841BF48DD300272920 /* TableSectionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508B71831BF48DD300272920 /* TableSectionBuilder.swift */; }; + 508B71861BF48E0D00272920 /* TableRowBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508B71851BF48E0D00272920 /* TableRowBuilder.swift */; }; + DA1BCD0F1BF5472C00CC0479 /* TableDirector.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA1BCD0E1BF5472C00CC0479 /* TableDirector.swift */; }; DAB7EB2B1BEF787300D2AD5E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB7EB2A1BEF787300D2AD5E /* AppDelegate.swift */; }; DAB7EB2D1BEF787300D2AD5E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB7EB2C1BEF787300D2AD5E /* ViewController.swift */; }; DAB7EB301BEF787300D2AD5E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DAB7EB2E1BEF787300D2AD5E /* Main.storyboard */; }; DAB7EB321BEF787300D2AD5E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DAB7EB311BEF787300D2AD5E /* Assets.xcassets */; }; DAB7EB351BEF787300D2AD5E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DAB7EB331BEF787300D2AD5E /* LaunchScreen.storyboard */; }; - DAB7EB3E1BEF78A400D2AD5E /* Tablet.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB7EB3D1BEF78A400D2AD5E /* Tablet.swift */; settings = {ASSET_TAGS = (); }; }; - DAB7EB401BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB7EB3F1BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift */; settings = {ASSET_TAGS = (); }; }; + DAB7EB3E1BEF78A400D2AD5E /* Tablet.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB7EB3D1BEF78A400D2AD5E /* Tablet.swift */; }; + DAB7EB401BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB7EB3F1BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 508B71831BF48DD300272920 /* TableSectionBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableSectionBuilder.swift; sourceTree = ""; }; 508B71851BF48E0D00272920 /* TableRowBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableRowBuilder.swift; sourceTree = ""; }; + DA1BCD0E1BF5472C00CC0479 /* TableDirector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableDirector.swift; sourceTree = ""; }; DAB7EB271BEF787300D2AD5E /* TabletDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TabletDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; DAB7EB2A1BEF787300D2AD5E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; DAB7EB2C1BEF787300D2AD5E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -78,8 +80,9 @@ isa = PBXGroup; children = ( DAB7EB3D1BEF78A400D2AD5E /* Tablet.swift */, - 508B71831BF48DD300272920 /* TableSectionBuilder.swift */, + DA1BCD0E1BF5472C00CC0479 /* TableDirector.swift */, 508B71851BF48E0D00272920 /* TableRowBuilder.swift */, + 508B71831BF48DD300272920 /* TableSectionBuilder.swift */, ); name = Tablet; path = ../Tablet; @@ -159,6 +162,7 @@ DAB7EB2D1BEF787300D2AD5E /* ViewController.swift in Sources */, DAB7EB3E1BEF78A400D2AD5E /* Tablet.swift in Sources */, 508B71861BF48E0D00272920 /* TableRowBuilder.swift in Sources */, + DA1BCD0F1BF5472C00CC0479 /* TableDirector.swift in Sources */, DAB7EB401BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift in Sources */, DAB7EB2B1BEF787300D2AD5E /* AppDelegate.swift in Sources */, ); diff --git a/TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/xcuserdata/maxsokolov.xcuserdatad/UserInterfaceState.xcuserstate b/TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/xcuserdata/maxsokolov.xcuserdatad/UserInterfaceState.xcuserstate index 4169e6efacb8dc7a04433b2f062c0fa4186df192..0a16516435f0dc4e8e84ace46b1e8ff879919f73 100644 GIT binary patch delta 7963 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 Jzo_in{{{E|K@I=_ diff --git a/TabletDemo/TabletDemo/ViewController.swift b/TabletDemo/TabletDemo/ViewController.swift index 848d2a2..842f30e 100644 --- a/TabletDemo/TabletDemo/ViewController.swift +++ b/TabletDemo/TabletDemo/ViewController.swift @@ -19,7 +19,7 @@ class ViewController: UIViewController { tableDirector = TableDirector(tableView: tableView) let rowBuilder = TableRowBuilder(items: [1, 2, 3, 4], id: "cell") - .action(.configure) { data -> Void in + .action(.configure) { data in data.cell?.textLabel?.text = "\(data.item)" } @@ -31,18 +31,18 @@ class ViewController: UIViewController { return false } - + let configurableRowBuilder = TableConfigurableRowBuilder(items: ["5", "6", "7", "8"]) - .action(kConfigurableTableViewCellButtonClickedAction) { data -> Void in - - print("custom action indexPath: \(data.indexPath), item: \(data.item)") - } .action(.click) { data -> Void in data.cell!.textLabel?.text = "" print("custom action indexPath: \(data.indexPath), item: \(data.item)") } + .action(kConfigurableTableViewCellButtonClickedAction) { data in + + print("custom action indexPath: \(data.indexPath), item: \(data.item)") + } let sectionBuilder = TableSectionBuilder(headerTitle: "Tablet", footerTitle: "Deal with table view like a boss.", rowBuilders: [rowBuilder, configurableRowBuilder])