From 0d9c0f4df685b7d7c9c7842daee9a682aa706b41 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 8 Nov 2015 15:34:35 +0300 Subject: [PATCH 01/25] added tablet sources, xcode demo project setup --- Tablet/Tablet.swift | 386 ++++++++++++++++++ .../TabletDemo.xcodeproj/project.pbxproj | 306 ++++++++++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 12263 bytes .../xcschemes/TabletDemo.xcscheme | 91 +++++ .../xcschemes/xcschememanagement.plist | 22 + TabletDemo/TabletDemo/AppDelegate.swift | 46 +++ .../AppIcon.appiconset/Contents.json | 38 ++ .../Base.lproj/LaunchScreen.storyboard | 27 ++ .../TabletDemo/Base.lproj/Main.storyboard | 25 ++ TabletDemo/TabletDemo/Info.plist | 38 ++ TabletDemo/TabletDemo/ViewController.swift | 25 ++ 12 files changed, 1011 insertions(+) create mode 100644 Tablet/Tablet.swift create mode 100644 TabletDemo/TabletDemo.xcodeproj/project.pbxproj create mode 100644 TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/xcuserdata/maxsokolov.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 TabletDemo/TabletDemo.xcodeproj/xcuserdata/maxsokolov.xcuserdatad/xcschemes/TabletDemo.xcscheme create mode 100644 TabletDemo/TabletDemo.xcodeproj/xcuserdata/maxsokolov.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 TabletDemo/TabletDemo/AppDelegate.swift create mode 100644 TabletDemo/TabletDemo/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 TabletDemo/TabletDemo/Base.lproj/LaunchScreen.storyboard create mode 100644 TabletDemo/TabletDemo/Base.lproj/Main.storyboard create mode 100644 TabletDemo/TabletDemo/Info.plist create mode 100644 TabletDemo/TabletDemo/ViewController.swift diff --git a/Tablet/Tablet.swift b/Tablet/Tablet.swift new file mode 100644 index 0000000..cb9b68b --- /dev/null +++ b/Tablet/Tablet.swift @@ -0,0 +1,386 @@ +// +// 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 + +internal let kActionPerformedNotificationKey = "_action" + +/** + Built in actions that Tablet provides. +*/ +public enum ActionType : String { + + case click = "_click" + case select = "_select" + case deselect = "_deselect" + case configure = "_configure" + case willDisplay = "_willDisplay" +} + +public struct ActionData { + + 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) { + + self.cell = cell + self.indexPath = indexPath + self.item = item + self.itemIndex = itemIndex + } +} + +public class Action { + + public let cell: UITableViewCell + public let key: String + public let userInfo: [NSObject: AnyObject]? + + public init(key: String, sender: UITableViewCell, userInfo: [NSObject: AnyObject]? = nil) { + self.key = key + self.cell = sender + self.userInfo = userInfo + } + + public func trigger() { + + NSNotificationCenter.defaultCenter().postNotificationName(kActionPerformedNotificationKey, object: self) + } +} + +/** + If you want to delegate your cell configuration logic to cell itself (with your view model or even model) than + just provide an implementation of this protocol for your cell. Enjoy strong typisation. +*/ +public protocol ConfigurableCell { + + typealias Item + + static func reusableIdentifier() -> String + func configureWithItem(item: Item) +} + +/** + A protocol that every row builder should follow. + A certain section can only works with row builders that respect this protocol. +*/ +public protocol ReusableRowBuilder { + + var numberOfRows: Int { get } + var reusableIdentifier: String { get } + + func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> Bool +} + +/** + A class that responsible for building cells of given type and passing items to them. +*/ +public class TableRowBuilder : ReusableRowBuilder { + + public typealias TableRowBuilderActionBlock = (data: ActionData) -> Void + + private var actions = Dictionary() + private var items = [I]() + + public var reusableIdentifier: String + public var numberOfRows: Int { + get { + return items.count + } + } + + public init(item: I, id: String) { + + reusableIdentifier = id + items.append(item) + } + + public init(items: [I]? = nil, id: String) { + + reusableIdentifier = id + + if items != nil { + self.items.appendContentsOf(items!) + } + } + + public func appendItems(items: [I]) { + + self.items.appendContentsOf(items) + } + + public func clear() { + + items.removeAll() + } + + // MARK: Chaining actions + + public func action(key: String, action: TableRowBuilderActionBlock) -> Self { + + actions[key] = action + return self + } + + public func action(key: ActionType, action: TableRowBuilderActionBlock) -> Self { + + actions[key.rawValue] = action + return self + } + + // MARK: Triggers + + public func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> Bool { + + let actionData = ActionData(cell: cell as! C, indexPath: indexPath, item: items[itemIndex], itemIndex: itemIndex) + + if let block = actions[key] { + block(data: actionData) + return true + } + return false + } +} + +/** + A class that responsible for building configurable cells of given type and passing items to them. +*/ +public class TableConfigurableRowBuilder : TableRowBuilder { + + public init(item: I) { + super.init(item: item, id: C.reusableIdentifier()) + } + + public init(items: [I]? = nil) { + super.init(items: items, id: C.reusableIdentifier()) + } + + public override func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> Bool { + + (cell as! C).configureWithItem(items[itemIndex]) + + return super.triggerAction(key, cell: cell, indexPath: indexPath, itemIndex: itemIndex) + } +} + +/** + A class that responsible for building a certain table view section. +*/ +public class TableSectionBuilder { + + private var builders = [ReusableRowBuilder]() + + public var headerTitle: String? + public var footerTitle: String? + + public var headerView: UIView? + public var headerHeight: CGFloat = UITableViewAutomaticDimension + + public var footerView: UIView? + public var footerHeight: CGFloat = UITableViewAutomaticDimension + + /// A total number of rows in section of each row builder. + public var numberOfRowsInSection: Int { + + var number = 0 + for builder in builders { + number += builder.numberOfRows + } + return number + } + + public init(headerTitle: String? = nil, footerTitle: String? = nil, rowBuilders: [ReusableRowBuilder]? = nil) { + + self.headerTitle = headerTitle + self.footerTitle = footerTitle + + if let initialRows = rowBuilders { + self.builders.appendContentsOf(initialRows) + } + } + + public init(headerView: UIView? = nil, headerHeight: CGFloat = UITableViewAutomaticDimension, footerView: UIView? = nil, footerHeight: CGFloat = UITableViewAutomaticDimension) { + + self.headerView = headerView + self.headerHeight = headerHeight + + self.footerView = footerView + self.footerHeight = footerHeight + } + + internal func builderAtIndex(var index: Int) -> (ReusableRowBuilder, Int)? { + + for builder in builders { + if index < builder.numberOfRows { + return (builder, index) + } + index -= builder.numberOfRows + } + + return nil + } +} + +/** + A class that actualy handles 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) -> (ReusableRowBuilder, Int) { + + return sections[indexPath.section].builderAtIndex(indexPath.row)! + } + + private func triggerAction(action: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath) -> Bool { + + 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) { + 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) + } +} \ No newline at end of file diff --git a/TabletDemo/TabletDemo.xcodeproj/project.pbxproj b/TabletDemo/TabletDemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1c74af6 --- /dev/null +++ b/TabletDemo/TabletDemo.xcodeproj/project.pbxproj @@ -0,0 +1,306 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 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 = (); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 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 = ""; }; + DAB7EB2F1BEF787300D2AD5E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + DAB7EB311BEF787300D2AD5E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + DAB7EB341BEF787300D2AD5E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + DAB7EB361BEF787300D2AD5E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DAB7EB3D1BEF78A400D2AD5E /* Tablet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tablet.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + DAB7EB241BEF787300D2AD5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + DAB7EB1E1BEF787300D2AD5E = { + isa = PBXGroup; + children = ( + DAB7EB3C1BEF789500D2AD5E /* Tablet */, + DAB7EB291BEF787300D2AD5E /* TabletDemo */, + DAB7EB281BEF787300D2AD5E /* Products */, + ); + sourceTree = ""; + }; + DAB7EB281BEF787300D2AD5E /* Products */ = { + isa = PBXGroup; + children = ( + DAB7EB271BEF787300D2AD5E /* TabletDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + DAB7EB291BEF787300D2AD5E /* TabletDemo */ = { + isa = PBXGroup; + children = ( + DAB7EB2A1BEF787300D2AD5E /* AppDelegate.swift */, + DAB7EB2C1BEF787300D2AD5E /* ViewController.swift */, + DAB7EB2E1BEF787300D2AD5E /* Main.storyboard */, + DAB7EB311BEF787300D2AD5E /* Assets.xcassets */, + DAB7EB331BEF787300D2AD5E /* LaunchScreen.storyboard */, + DAB7EB361BEF787300D2AD5E /* Info.plist */, + ); + path = TabletDemo; + sourceTree = ""; + }; + DAB7EB3C1BEF789500D2AD5E /* Tablet */ = { + isa = PBXGroup; + children = ( + DAB7EB3D1BEF78A400D2AD5E /* Tablet.swift */, + ); + name = Tablet; + path = ../Tablet; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + DAB7EB261BEF787300D2AD5E /* TabletDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = DAB7EB391BEF787300D2AD5E /* Build configuration list for PBXNativeTarget "TabletDemo" */; + buildPhases = ( + DAB7EB231BEF787300D2AD5E /* Sources */, + DAB7EB241BEF787300D2AD5E /* Frameworks */, + DAB7EB251BEF787300D2AD5E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = TabletDemo; + productName = TabletDemo; + productReference = DAB7EB271BEF787300D2AD5E /* TabletDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DAB7EB1F1BEF787300D2AD5E /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0700; + ORGANIZATIONNAME = Tablet; + TargetAttributes = { + DAB7EB261BEF787300D2AD5E = { + CreatedOnToolsVersion = 7.0.1; + }; + }; + }; + buildConfigurationList = DAB7EB221BEF787300D2AD5E /* Build configuration list for PBXProject "TabletDemo" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = DAB7EB1E1BEF787300D2AD5E; + productRefGroup = DAB7EB281BEF787300D2AD5E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DAB7EB261BEF787300D2AD5E /* TabletDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + DAB7EB251BEF787300D2AD5E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DAB7EB351BEF787300D2AD5E /* LaunchScreen.storyboard in Resources */, + DAB7EB321BEF787300D2AD5E /* Assets.xcassets in Resources */, + DAB7EB301BEF787300D2AD5E /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + DAB7EB231BEF787300D2AD5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DAB7EB2D1BEF787300D2AD5E /* ViewController.swift in Sources */, + DAB7EB3E1BEF78A400D2AD5E /* Tablet.swift in Sources */, + DAB7EB2B1BEF787300D2AD5E /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + DAB7EB2E1BEF787300D2AD5E /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + DAB7EB2F1BEF787300D2AD5E /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + DAB7EB331BEF787300D2AD5E /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + DAB7EB341BEF787300D2AD5E /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + DAB7EB371BEF787300D2AD5E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + 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_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + DAB7EB381BEF787300D2AD5E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + 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_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + DAB7EB3A1BEF787300D2AD5E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = TabletDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.tablet.TabletDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + DAB7EB3B1BEF787300D2AD5E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = TabletDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.tablet.TabletDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + DAB7EB221BEF787300D2AD5E /* Build configuration list for PBXProject "TabletDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DAB7EB371BEF787300D2AD5E /* Debug */, + DAB7EB381BEF787300D2AD5E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DAB7EB391BEF787300D2AD5E /* Build configuration list for PBXNativeTarget "TabletDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DAB7EB3A1BEF787300D2AD5E /* Debug */, + DAB7EB3B1BEF787300D2AD5E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = DAB7EB1F1BEF787300D2AD5E /* Project object */; +} diff --git a/TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..9fbb493 --- /dev/null +++ b/TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/xcuserdata/maxsokolov.xcuserdatad/UserInterfaceState.xcuserstate b/TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/xcuserdata/maxsokolov.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..77672232c294afb01b19a607b6399e4524971cbc GIT binary patch literal 12263 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 literal 0 HcmV?d00001 diff --git a/TabletDemo/TabletDemo.xcodeproj/xcuserdata/maxsokolov.xcuserdatad/xcschemes/TabletDemo.xcscheme b/TabletDemo/TabletDemo.xcodeproj/xcuserdata/maxsokolov.xcuserdatad/xcschemes/TabletDemo.xcscheme new file mode 100644 index 0000000..6db4123 --- /dev/null +++ b/TabletDemo/TabletDemo.xcodeproj/xcuserdata/maxsokolov.xcuserdatad/xcschemes/TabletDemo.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TabletDemo/TabletDemo.xcodeproj/xcuserdata/maxsokolov.xcuserdatad/xcschemes/xcschememanagement.plist b/TabletDemo/TabletDemo.xcodeproj/xcuserdata/maxsokolov.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..c382e1a --- /dev/null +++ b/TabletDemo/TabletDemo.xcodeproj/xcuserdata/maxsokolov.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + TabletDemo.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + DAB7EB261BEF787300D2AD5E + + primary + + + + + diff --git a/TabletDemo/TabletDemo/AppDelegate.swift b/TabletDemo/TabletDemo/AppDelegate.swift new file mode 100644 index 0000000..5453072 --- /dev/null +++ b/TabletDemo/TabletDemo/AppDelegate.swift @@ -0,0 +1,46 @@ +// +// AppDelegate.swift +// TabletDemo +// +// Created by Max Sokolov on 08/11/15. +// Copyright © 2015 Tablet. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(application: UIApplication) { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/TabletDemo/TabletDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/TabletDemo/TabletDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..118c98f --- /dev/null +++ b/TabletDemo/TabletDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/TabletDemo/TabletDemo/Base.lproj/LaunchScreen.storyboard b/TabletDemo/TabletDemo/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..2e721e1 --- /dev/null +++ b/TabletDemo/TabletDemo/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TabletDemo/TabletDemo/Base.lproj/Main.storyboard b/TabletDemo/TabletDemo/Base.lproj/Main.storyboard new file mode 100644 index 0000000..3a2a49b --- /dev/null +++ b/TabletDemo/TabletDemo/Base.lproj/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TabletDemo/TabletDemo/Info.plist b/TabletDemo/TabletDemo/Info.plist new file mode 100644 index 0000000..6c48029 --- /dev/null +++ b/TabletDemo/TabletDemo/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + + diff --git a/TabletDemo/TabletDemo/ViewController.swift b/TabletDemo/TabletDemo/ViewController.swift new file mode 100644 index 0000000..327c880 --- /dev/null +++ b/TabletDemo/TabletDemo/ViewController.swift @@ -0,0 +1,25 @@ +// +// ViewController.swift +// TabletDemo +// +// Created by Max Sokolov on 08/11/15. +// Copyright © 2015 Tablet. All rights reserved. +// + +import UIKit + +class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view, typically from a nib. + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + +} + From d5639127f2986caf796f9550457477687edb7263 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 8 Nov 2015 15:55:06 +0300 Subject: [PATCH 02/25] bump readme --- README.md | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 240f65f..a23f7e4 100644 --- a/README.md +++ b/README.md @@ -1 +1,44 @@ -# Tablet \ No newline at end of file +# tablet + +Tablet is a super lightweight yet powerful library that handles a complexity of UITableView's datasource and delegate. + +## Requirements + +- iOS 7.0+ +- Xcode 7.0+ + +## Usage + +### Very basic + +```swift +import Tablet + +let rowBuilder = TableRowBuilder(items: [user1, user2, user3], id: "reusable_id") + .action(.configure) { data in + + data.cell.textLabel?.text = data.item.title + data.cell.detailTextLabel?.text = data.item.isActive ? "Active" : "Inactive" + } + +let sectionBuilder = TableSectionBuilder(headerTitle: "Users", rowBuilders: [rowBuilder]) + +let director = TableDirector(tableView: tableView) +director.appendSections(sectionBuilder) +``` + +### Additional cell actions + +```swift + +let rowBuilder = TableRowBuilder(items: [user1, user2, user3], id: "reusable_id") + .action(.configure) { data in + + } + .action(.click) { data in + + } + .action(.willDisplay) { data in + + } +``` \ No newline at end of file From 94aacbcbe3348e20bd40fba866271b4b4687ec5f Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 8 Nov 2015 20:03:35 +0300 Subject: [PATCH 03/25] bump readme --- README.md | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a23f7e4..d792852 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Tablet is a super lightweight yet powerful library that handles a complexity of ## Requirements -- iOS 7.0+ +- iOS 8.0+ - Xcode 7.0+ ## Usage @@ -30,6 +30,7 @@ director.appendSections(sectionBuilder) ### Additional cell actions ```swift +import Tablet let rowBuilder = TableRowBuilder(items: [user1, user2, user3], id: "reusable_id") .action(.configure) { data in @@ -41,4 +42,37 @@ let rowBuilder = TableRowBuilder(items: [user1, user2, us .action(.willDisplay) { data in } +``` + +### Configurable cells + +Let's say you want to put your cell configuration logic into cell itself. Say you want to pass your view model (or even model) to your cell. +To provide this behaviour simply follow: + +```swift +import Tablet + +class UserTableViewCell : UITableViewCell, ConfigurableCell { + + typealias Item = User + + static func reusableIdentifier() -> String { + return "reusable_id" + } + + func configureWithItem(item: Item) { // item is user here + + textLabel?.text = item.title + detailTextLabel?.text = item.isActive ? "Active" : "Inactive" + } +} +``` +Once you follow the protocol, simply use TableConfigurableRowBuilder to build cells: + +```swift +import Tablet + +let rowBuilder = TableConfigurableRowBuilder() + +tableDirector.appendSection(TableSectionBuilder(rowBuilders: [rowBuilder])) ``` \ No newline at end of file From 469952625ca61be8dc225b724cc589079cae0bce Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 8 Nov 2015 21:05:52 +0300 Subject: [PATCH 04/25] bump readme --- README.md | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d792852..3e46306 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ let director = TableDirector(tableView: tableView) director.appendSections(sectionBuilder) ``` -### Additional cell actions +### Cell actions ```swift import Tablet @@ -73,6 +73,35 @@ Once you follow the protocol, simply use TableConfigurableRowBuilder to build ce import Tablet let rowBuilder = TableConfigurableRowBuilder() +rowBuilder.appendItems(users) tableDirector.appendSection(TableSectionBuilder(rowBuilders: [rowBuilder])) +``` + +### Custom cell actions +```swift +import Tablet + +class UserTableViewCell : UITableViewCell { + + @IBAction func shareButtonClicked(sender: UIButton) { + + Action(key: "action_key", sender: self).trigger() + } +} +``` +And receive this actions with your row builder: +```swift +import Tablet + +let rowBuilder = TableRowBuilder(items: users, id: "reusable_id") + .action(.click) { data in + + } + .action(.willDisplay) { data in + + } + .action("action_key") { data in + + } ``` \ No newline at end of file From a413b4f87e03eb06ca39b1ca15608052b3d17b2d Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 8 Nov 2015 22:27:55 +0300 Subject: [PATCH 05/25] provide demo project --- README.md | 8 +- .../TabletDemo.xcodeproj/project.pbxproj | 4 + .../UserInterfaceState.xcuserstate | Bin 12263 -> 21145 bytes TabletDemo/TabletDemo/AppDelegate.swift | 33 +----- .../Base.lproj/LaunchScreen.storyboard | 5 +- .../TabletDemo/Base.lproj/Main.storyboard | 94 +++++++++++++++++- .../ConfigurableTableViewCell.swift | 33 ++++++ TabletDemo/TabletDemo/ViewController.swift | 36 +++++-- 8 files changed, 163 insertions(+), 50 deletions(-) create mode 100644 TabletDemo/TabletDemo/ConfigurableTableViewCell.swift diff --git a/README.md b/README.md index 3e46306..3935676 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ director.appendSections(sectionBuilder) ### Cell actions +Tablet provides a chaining approach to handle actions from your cells: + ```swift import Tablet @@ -84,9 +86,9 @@ import Tablet class UserTableViewCell : UITableViewCell { - @IBAction func shareButtonClicked(sender: UIButton) { + @IBAction func buttonClicked(sender: UIButton) { - Action(key: "action_key", sender: self).trigger() + Action(key: "action_key", sender: self, userInfo: nil).trigger() } } ``` @@ -94,7 +96,7 @@ And receive this actions with your row builder: ```swift import Tablet -let rowBuilder = TableRowBuilder(items: users, id: "reusable_id") +let rowBuilder = TableRowBuilder(items: users, id: "reusable_id") .action(.click) { data in } diff --git a/TabletDemo/TabletDemo.xcodeproj/project.pbxproj b/TabletDemo/TabletDemo.xcodeproj/project.pbxproj index 1c74af6..3c3b98c 100644 --- a/TabletDemo/TabletDemo.xcodeproj/project.pbxproj +++ b/TabletDemo/TabletDemo.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 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 = (); }; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -24,6 +25,7 @@ DAB7EB341BEF787300D2AD5E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; DAB7EB361BEF787300D2AD5E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DAB7EB3D1BEF78A400D2AD5E /* Tablet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tablet.swift; sourceTree = ""; }; + DAB7EB3F1BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurableTableViewCell.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -59,6 +61,7 @@ children = ( DAB7EB2A1BEF787300D2AD5E /* AppDelegate.swift */, DAB7EB2C1BEF787300D2AD5E /* ViewController.swift */, + DAB7EB3F1BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift */, DAB7EB2E1BEF787300D2AD5E /* Main.storyboard */, DAB7EB311BEF787300D2AD5E /* Assets.xcassets */, DAB7EB331BEF787300D2AD5E /* LaunchScreen.storyboard */, @@ -148,6 +151,7 @@ files = ( DAB7EB2D1BEF787300D2AD5E /* ViewController.swift in Sources */, DAB7EB3E1BEF78A400D2AD5E /* Tablet.swift in Sources */, + DAB7EB401BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift in Sources */, DAB7EB2B1BEF787300D2AD5E /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; 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 77672232c294afb01b19a607b6399e4524971cbc..daf4a1ae6ef4382ff03e0752c1edcbec2e236f3c 100644 GIT binary patch literal 21145 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 delta 7284 zcmaJ_34Bb~_rJ?zmdyTU-eeZD>x?BKkwj2SBC(T_%^D*Z1W9Bgv2@O;qE)qwrPP+h zz7$oJTBwefs%(A9?fMJ?GqWzvp|;Iqxo7g|B&L^8x`U z(9AJ3@ZmTlLSm#rTErtaYJeJ|MyN50L{X>-YKl6bj;IsrjJlw%s2l2zdZ1MF8tRFL zq2Xu*%0(m5C^Q=7p?p+;#-TURO!O|AhZdvB=zUa)R--j&1KNl-qwVNpv=e=b_MwC5 zYjgyiM5oYMbPoBhq3h^ZbOYVO2xCkz#R43Lg;<2eSc`eA!x31I4cLfHxE{9RS8!w8 z6vyHO+yb}8ZE!N~h`Zn(I2HH9{qX>tjR)e9coZIu^Kd>c#N%)oo`m1TQ}HxB9lwR= z;JG+}058Bx@KRji!)x$bya{i|ALAW(Fa8XFjt}B*@CkeppTg(y&-fa?j(^2B@MHW0 z|Be5_Pw~G55g`!~IZ+TjF%Tm$5j$~{C=yFrk~SonbRoS+8c8Sp$pDf~ykr;|PDYVQ zTDfd4o(L?~s|qH=isbi^(#woNOQ)$tLmv*-W;Ro#YF$kL)K0$d}|ha)f+O zj*^q)CvujYBfpTVrpecP#1O61~igJ(|FpP zwx#W8B2A+0X-Aq$(`Y*N&_OiENAqYtEuf`zEFDK@(0Axe`YxSCXVW=!E)CFmbUs}` z7t;4=C9R?>=_b>kS~Z7z=x0#ST5+?&VpQPPz2H=12Q5L zs)x)F20{>l7$gu5(lyA6Y{-t}Or$=l4>FL$Rv=77&n{1(N!YZ+=Pc zuv~9ZW|#b--ZE&&{B2wZj$>#ET8fsT<$*%6HqcpR4XZ>eP(|>UuTN_FYlBC6hm_P> ztqNL&sGyOo8cb_P)`mu!21okUjHGz;3TljRLLc-_O;0K+$|PP|F!xk`29of1L+`}QHt(>ydf}!3@^i^=$&&60qSNTd;Oiftbp<*DZNQV!BPTb%mWk)lCB#*spV0+$5!ymK zNUTDa8KA#F5(9J)+m>!kP6qld=;uvnAB=L%*1e4$2KVY6bQj%2_t78d0s0e?Aq6@> zN9Y8dq01Wd7kY#qGd?Ut|DdPP6}mwtqd`L$0NKpDvzmoXY`~HDAo=nZ|K@BdJ_hPjMwNg;Z_ zM8szdWEC{X&3^yGz&czDu?hudHEHC-ZIKkWLnSx~eaOh!WN=Qgw?DfVc}FusjrB5q z41{Jii%P*AGE>tTKPzzxs;GI_33p~pOik}mS`y4HFIHTII|bKVv#72tVz?XRK(t52 zPpAPZ(l#L`Ca|}msu6w-XCT)~+!Oc0X*eB*z)`k2wVC0V)Naa~HhdBrtem*a_*cs!l}W1tkuo^cJoj{S(M#6ApA z2t}26GJXS!p@gwQ6>InP>FymCvg1sgJRJr9)#|;CXV%es7teyRFb*>MrsWPFQLEE4 zq*H_KJUoBkb7VtlqYBTfNgN^COea z@kM+I-i29}_zM07X2TrD!WNR8R`@r354l$3oA`Hp3*W|f@LiY-0hkB#VF4^$jql?> z@B@}N9&ig2)$m8)g! zA$YNe;N|K0l9ERi2$#xy@hu~53Gs20Ce<3LM=Z~MvO)!9)DAdE{pTLM0+r9nMjDVt zYyee3R0U}aRWAmbkm%sRLTFeK@}ZWVB#tzHHixf*B*3Z{le8kQ)?qSfOA?ul(Do%s zu;v*rND7`SW(}(nhjj#za>h@gD#JOW$W(*lfa_Z;}W^-+RF;`|uE=w}GER>;!ty7>d zp;LB<*JMPnr0H4bSXY=@6w2UNo+YfybMmW(51 zq@0W=6IjCA3IF;r@ne-AH}m6IMz#E?y+-mTna+qzrlNmf7YwK*Z;`iQH~h(lGn=$Z zsEy~lWKK|O7MTruU~eUvO9JpYoMqvAQ6tEEp?dJCN0k)FaoPhK~}LeO)5wwsUj=k3)lzy;lN6=nyevf$vXHFzK5gmQ_#!!0ReBb>`r70`S5vk zx52^M=zh$0J=sC3;ShZLBC@;4rwnbfo9uzZ@Kq(*OFo0I;hRt*&a{$)-0hO&K{&ejq=RGkuG_qgmU>YB-#P6L1{P zyjXd(k(?(NgOL49F2E@`T}dvH%kTsI$X3)nE;`t;ksIW zJOIzOw(&8z6Ah=bAZ)?(PUY~+GuWt#!A8}TgRAiCbJ!?P^)Hi@8mJMj!F2{(Osp%? zoA@%Lsg*ij7REe61heJT1`I=cHf>1Rb`KVt5SlcKp-G#-t(VZGF|-+3O3uI? zxDB7d8E4Y2+hto)#Hwf1qY0FKAXU;9v?bhydzJK6+8XY|9}LH939ly6WSUY3FWQNA zW%B4L?ZSGuhn2J&?GBIN?>bbay+U04%cII-RP7LmZpry-x<#5n`v&`m|LyZ=KiWUk z=RJleEKjF{C*Zpg+z@bo1cJDtuAeJ40Wy<%K+ZEmGw zXc5bMw9t=H1ugbt%!2T^m8~}|qpZhROUvnaI)P54lj!TzN5PM&9}E0A%#VeBEb?Qq zA4~i=d@Y^KKFX5ln{+CjMyI3tek^6#AkB|uek}K6g&!-~b4H->)ng;0J9KQH5|h$A zDkeTQHY%=Tbc?9=$;mNMF|qBFk~_w3i7>uYi=zfo7FCU z5naj(3tdd#r%U`;?Z=!SYpUonx}30IT0f3~Wh{7`T8~bntMSBDbPZig*U|NKgCFyL zT+fefe$2dV_=1%mP`2}{=w`ZwZuMiGA4mAHzKU+6AJOf8Z17{FADe=Giz~1t$r5<0 z%@iN~lz#DFI{WB;dccp(er)k$D~n7UF*5|&ULnYKj9x)f z`U}0f?d!G$#MdCy^U>?{*X-v#UrJ6%P8EA~165?PuL<^4JLgS$pJfaN*DZRRZl!nW zy%1=P{J1g0&5tAfIBGTBhI`XL=|k2-_huMExgR(2<7n1Omj{t_u=1D0lH1talJc~` z?xfj10YXv%7LeeFK=2bZ#Q*B--En^0G~}K@APB4R#9Jv4po)PR1w(VnZ8;^jnD|z) zajF}k93YV3i4{oBPD09Rp5?4M2X`wgEo{HSUMOQ7U}}0dZ@G79QqhnR>^r0As6guz z@R{i)IVE1e>!Yx{qEH=maeU8G-`AG{HQ<8o@fj2Eiu5 zX2Dj$Ho@IT zXV}58Lt!Vwu7}+SyBT&X>`vIdus_274ErnWu~05l3e`f5kQYV>4MLO9EVK&k!bo8U zVY+anuv9oh_<`^X;Ys0D;S&)riWW5!#fh4WT8Mgy`uRjTqCC-T(Gt-z(F#$eXr*Yi zXsu|E=zG!6qI+V6SS9AfTCq;77k3q>i~ETOhzE)Xi3f`d#N)*vo-Cdso+=KAmx$Mh zw}_93Pl)e}|CUH3Qi)uml;|W*$tx1Kq@g5E(niuj(pA!1GDMOmDUcLOiY3*O&n2fN zzO#~hk|*J=@W$a;;RWG^;l<&l;p4&~{EhH8!>5JM4&NERH~iP|ds4mBEKQd7l%`8F zrG2FRqywZ=q;sV6qzj~rr0+|YN-L$Cr5{VHr8}j&rTe4@qz9#krC&=Q%9JvoSndlr55dBs(O#A}4Z% zyuLg}-b&tD-d3I{Z!hmA?;(Fp-bQsF+ed;F-Vc8C{PqCiWR=s6*Ckw6|)p` z6gw3M6-N|5Db6W=R$NrvP~1^GP&`#?l_q67^ zeB~Hrk+MWNNjYD+Lb+bKL;0EV3*~<0m&!xRqsrsTlgiV|AC*5TAE|VzmZ~&Wf7Jlh zK-DN!zG{rBSXHVT=Tps4%~LH>y{}rTTCUot+N#>7+OFEE+O7Ij^_l8B)kW0})qOQm zhp9zsiCUpnsX4V)ZBe_`(du^Uj_P!Emb#C+zdBp(Q5UO0?N?7$Pf^cN&r>f@FH*m+ zUaH=z-l^WJ{#?CJeL#IoeOmpa`X}`T^(FNc^;Pv9weJxp6728#G5WPqk)kBW;wnskWImPTO4DS(~ZtqwS~7)_Sx#+R@r_Eodier)Z~Y zXKH6@=V$}k`Pv2A3T?IafcB8~EA6-1Bif_d^V*Br%i62j>)IRIhuX*5zqSAJn5Vpo z*YG^A=Z$%;Xjy+WU+ z_vmxjsUXy`j*s*s#X1-muZI*|62% z+h*8p_}sA1aKLcTaKiAT;U~j6!zIHN!&Sp|!=FZpG0NE7m~8B9>}u?8>}5 zYRWg2n&z7}n5s>mn0A_Wn+}^!`Ak2U&X~@c&YLcnE}3qd?wanK9+)1Q9+{q){;3yL zuTQ;c^|sf$VwRiT<~VbLxuvXi^jrRA}l_G#bl{(iLo@d zw6L_Yw6i2xk}Vx9JuDd(kEPr))iTX8-SW0&p=F6>nPr7#m1T`(on?ci+OpHK+w!S3 z!dl-NWo>GWvBp~Ct!=G|*7nvEYe#EmYcFem>j-P1wb)u}9cL}KPPR_5PPIg1htA~ehR zIPN&(IOn+Fxa_#$_}y{Gao_R4@zjZ&LZ`-Qbef$ur_ zLCzu0Va{CV7-z9_th3xX!8ye_!#U5n#D!e~m)vD?Ib020&0Wc^j;=1Q?ylEdX~SHZ zuE8#^Yq)EqE6-KnDs&aQ-gE77U3075Mz_P=*xkgP;BMB+}Z9y?!oS%?mTyi gd#t<6J>EUh{jNLUUR2X%5mIv(=xXk@f8Fo@9|-n-761SM diff --git a/TabletDemo/TabletDemo/AppDelegate.swift b/TabletDemo/TabletDemo/AppDelegate.swift index 5453072..69cc0e6 100644 --- a/TabletDemo/TabletDemo/AppDelegate.swift +++ b/TabletDemo/TabletDemo/AppDelegate.swift @@ -12,35 +12,4 @@ import UIKit class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - - - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { - // Override point for customization after application launch. - return true - } - - func applicationWillResignActive(application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(application: UIApplication) { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } - - -} - +} \ No newline at end of file diff --git a/TabletDemo/TabletDemo/Base.lproj/LaunchScreen.storyboard b/TabletDemo/TabletDemo/Base.lproj/LaunchScreen.storyboard index 2e721e1..ffacbd6 100644 --- a/TabletDemo/TabletDemo/Base.lproj/LaunchScreen.storyboard +++ b/TabletDemo/TabletDemo/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,8 @@ - + - + + diff --git a/TabletDemo/TabletDemo/Base.lproj/Main.storyboard b/TabletDemo/TabletDemo/Base.lproj/Main.storyboard index 3a2a49b..98f93de 100644 --- a/TabletDemo/TabletDemo/Base.lproj/Main.storyboard +++ b/TabletDemo/TabletDemo/Base.lproj/Main.storyboard @@ -1,13 +1,14 @@ - + - + + - + @@ -15,11 +16,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TabletDemo/TabletDemo/ConfigurableTableViewCell.swift b/TabletDemo/TabletDemo/ConfigurableTableViewCell.swift new file mode 100644 index 0000000..3d96de5 --- /dev/null +++ b/TabletDemo/TabletDemo/ConfigurableTableViewCell.swift @@ -0,0 +1,33 @@ +// +// ConfigurableTableViewCell.swift +// TabletDemo +// +// Created by Max Sokolov on 08/11/15. +// Copyright © 2015 Tablet. All rights reserved. +// + +import UIKit + +let kConfigurableTableViewCellButtonClickedAction = "button_clicked" + +class ConfigurableTableViewCell: UITableViewCell, ConfigurableCell { + + typealias Item = String + + @IBOutlet weak var button: UIButton! + + static func reusableIdentifier() -> String { + + return "configurable_cell" + } + + func configureWithItem(item: Item) { + + button.setTitle("Button \(item)", forState: .Normal) + } + + @IBAction func buttonClicked(sender: UIButton) { + + Action(key: kConfigurableTableViewCellButtonClickedAction, sender: self).trigger() + } +} \ No newline at end of file diff --git a/TabletDemo/TabletDemo/ViewController.swift b/TabletDemo/TabletDemo/ViewController.swift index 327c880..8dd2ca5 100644 --- a/TabletDemo/TabletDemo/ViewController.swift +++ b/TabletDemo/TabletDemo/ViewController.swift @@ -10,16 +10,32 @@ import UIKit class ViewController: UIViewController { + @IBOutlet weak var tableView: UITableView! + var tableDirector: TableDirector! + override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. + + tableDirector = TableDirector(tableView: tableView) + + let rowBuilder = TableRowBuilder(items: [1, 2, 3, 4], id: "cell") + .action(.configure) { data in + + data.cell.textLabel?.text = "\(data.item)" + } + + let configurableRowBuilder = TableConfigurableRowBuilder(items: ["5", "6", "7", "8"]) + .action(kConfigurableTableViewCellButtonClickedAction) { data in + + print("custom action indexPath: \(data.indexPath), item: \(data.item)") + } + .action(.click) { 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]) + + tableDirector.appendSection(sectionBuilder) } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - -} - +} \ No newline at end of file From 5207867e4cb0e8b711e8f56bd02c85fa1071767c Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 8 Nov 2015 22:59:35 +0300 Subject: [PATCH 06/25] bump readme, added installation section --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index 3935676..9d1aa19 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,25 @@ Tablet is a super lightweight yet powerful library that handles a complexity of - iOS 8.0+ - Xcode 7.0+ +## Installation + +### CocoaPods +To integrate Tablet into your Xcode project using CocoaPods, specify it in your `Podfile`: + +```ruby +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '8.0' +use_frameworks! + +pod 'Tablet' +``` + +Then, run the following command: + +```bash +$ pod install +``` + ## Usage ### Very basic From 5bb8f0d319beea3606e6f02b1ee9253189e86056 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 8 Nov 2015 23:20:01 +0300 Subject: [PATCH 07/25] added logo --- Tablet/Tablet.png | Bin 0 -> 45947 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tablet/Tablet.png diff --git a/Tablet/Tablet.png b/Tablet/Tablet.png new file mode 100644 index 0000000000000000000000000000000000000000..b586c7d37b6eb6aed69a5172c68d6b9e77a4f124 GIT binary patch literal 45947 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 yTloHO!~ZS#|1|tRcl Date: Sun, 8 Nov 2015 23:22:57 +0300 Subject: [PATCH 08/25] bump readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d1aa19..8a153b7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# tablet +![Tablet](https://raw.githubusercontent.com/maxsokolov/tablet/develop/Tablet/Tablet.png) Tablet is a super lightweight yet powerful library that handles a complexity of UITableView's datasource and delegate. From acd77aa3740f4a163d57bfeecd9fd66479e6e336 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 8 Nov 2015 23:31:21 +0300 Subject: [PATCH 09/25] added logo --- README.md | 2 +- Tablet/Tablet.png | Bin 45947 -> 0 bytes 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 Tablet/Tablet.png diff --git a/README.md b/README.md index 8a153b7..f8fdc6a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Tablet](https://raw.githubusercontent.com/maxsokolov/tablet/develop/Tablet/Tablet.png) +![Tablet](https://raw.githubusercontent.com/maxsokolov/tablet/assets/tablet.png) Tablet is a super lightweight yet powerful library that handles a complexity of UITableView's datasource and delegate. diff --git a/Tablet/Tablet.png b/Tablet/Tablet.png deleted file mode 100644 index b586c7d37b6eb6aed69a5172c68d6b9e77a4f124..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45947 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 yTloHO!~ZS#|1|tRcl Date: Sun, 8 Nov 2015 23:47:15 +0300 Subject: [PATCH 10/25] added podspec and license --- LICENSE | 19 +++++++++++++++++++ README.md | 2 +- Tablet.podspec | 16 ++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 LICENSE create mode 100644 Tablet.podspec diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..771048b --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +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. \ No newline at end of file diff --git a/README.md b/README.md index f8fdc6a..654efde 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Tablet](https://raw.githubusercontent.com/maxsokolov/tablet/assets/tablet.png) -Tablet is a super lightweight yet powerful library that handles a complexity of UITableView's datasource and delegate. +Tablet is a super lightweight yet powerful library that handles a complexity of UITableView's datasource and delegate in a Swift environment. ## Requirements diff --git a/Tablet.podspec b/Tablet.podspec new file mode 100644 index 0000000..5d4d01f --- /dev/null +++ b/Tablet.podspec @@ -0,0 +1,16 @@ +Pod::Spec.new do |s| + s.name = 'Tablet' + s.version = '0.1.0' + + s.homepage = 'https://github.com/maxsokolov/tablet' + s.summary = 'Tablet is a super lightweight yet powerful Swift library that handles a complexity of UITableView's datasource and delegate.' + + s.author = { 'Max Sokolov' => 'i@maxsokolov.net' } + s.license = { :type => 'MIT', :file => 'LICENSE' } + s.platforms = { :ios => '8.0' } + s.ios.deployment_target = '8.0' + + s.source_files = 'Tablet/*.swift' + s.module_name = 'Tablet' + s.source = { :git => 'https://github.com/maxsokolov/tablet.git', :tag => s.version } +end \ No newline at end of file From cc69a5e8d71d6182c3ff1b3cd2478c0311f9988e Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Mon, 9 Nov 2015 00:29:57 +0300 Subject: [PATCH 11/25] bump readme --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 654efde..fd08b41 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Tablet](https://raw.githubusercontent.com/maxsokolov/tablet/assets/tablet.png) -Tablet is a super lightweight yet powerful library that handles a complexity of UITableView's datasource and delegate in a Swift environment. +Tablet is a super lightweight yet powerful generic library that handles a complexity of UITableView's datasource and delegate in a Swift environment. Tablet's goal is to provide an easiest way to create complex table views. With Tablet you don't have to write a messy code of switch or if statement when you deal with bunch of different cells in different sections. ## Requirements @@ -125,4 +125,8 @@ let rowBuilder = TableRowBuilder(items: users, id: "reu .action("action_key") { data in } -``` \ No newline at end of file +``` + +## License + +Tablet is available under the MIT license. See LICENSE for details. \ No newline at end of file From 5b639c4483bcc950b75bdadffb2430777a88663e Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Tue, 10 Nov 2015 20:20:27 +0300 Subject: [PATCH 12/25] actionWithReturnValue --- Tablet/Tablet.swift | 21 ++++ .../UserInterfaceState.xcuserstate | Bin 0 -> 11439 bytes .../xcschemes/TabletDemo.xcscheme | 91 ++++++++++++++++++ .../xcschemes/xcschememanagement.plist | 22 +++++ TabletDemo/TabletDemo/ViewController.swift | 6 +- 5 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/xcuserdata/max.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 TabletDemo/TabletDemo.xcodeproj/xcuserdata/max.xcuserdatad/xcschemes/TabletDemo.xcscheme create mode 100644 TabletDemo/TabletDemo.xcodeproj/xcuserdata/max.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/Tablet/Tablet.swift b/Tablet/Tablet.swift index cb9b68b..f6cd97f 100644 --- a/Tablet/Tablet.swift +++ b/Tablet/Tablet.swift @@ -33,6 +33,9 @@ public enum ActionType : String { case deselect = "_deselect" case configure = "_configure" case willDisplay = "_willDisplay" + case shouldHighlight = "_shouldHighlight" + + } public struct ActionData { @@ -99,6 +102,7 @@ public protocol ReusableRowBuilder { public class TableRowBuilder : ReusableRowBuilder { public typealias TableRowBuilderActionBlock = (data: ActionData) -> Void + public typealias TableRowBuilderReturnValueActionBlock = (data: ActionData) -> AnyObject private var actions = Dictionary() private var items = [I]() @@ -149,6 +153,18 @@ public class TableRowBuilder : ReusableRowBuilder return self } + public func action(key: ActionType, action: TableRowBuilderReturnValueActionBlock) -> Self { + + + return self + } + + public func actionWithReturnValue(key: ActionType, action: (ActionData) -> Bool) -> Self { + + + return self + } + // MARK: Triggers public func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> Bool { @@ -383,4 +399,9 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate triggerAction(.willDisplay, cell: cell, indexPath: indexPath) } + + public func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool { + + return false + } } \ No newline at end of file diff --git a/TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/xcuserdata/max.xcuserdatad/UserInterfaceState.xcuserstate b/TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/xcuserdata/max.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..463604bc827b712334ee2b0e707fadcb314a5b97 GIT binary patch literal 11439 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 %aB9lFq%S+vS--|2vMG6DSS>*c_QQZ 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TabletDemo/TabletDemo.xcodeproj/xcuserdata/max.xcuserdatad/xcschemes/xcschememanagement.plist b/TabletDemo/TabletDemo.xcodeproj/xcuserdata/max.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..c382e1a --- /dev/null +++ b/TabletDemo/TabletDemo.xcodeproj/xcuserdata/max.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + TabletDemo.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + DAB7EB261BEF787300D2AD5E + + primary + + + + + diff --git a/TabletDemo/TabletDemo/ViewController.swift b/TabletDemo/TabletDemo/ViewController.swift index 8dd2ca5..ca9f5e8 100644 --- a/TabletDemo/TabletDemo/ViewController.swift +++ b/TabletDemo/TabletDemo/ViewController.swift @@ -30,9 +30,13 @@ class ViewController: UIViewController { print("custom action indexPath: \(data.indexPath), item: \(data.item)") } .action(.click) { data in - + print("custom action indexPath: \(data.indexPath), item: \(data.item)") } + .action(.shouldHighlight) { _ in + + return false + } let sectionBuilder = TableSectionBuilder(headerTitle: "Tablet", footerTitle: "Deal with table view like a boss.", rowBuilders: [rowBuilder, configurableRowBuilder]) From f4d59fedcb44a31b08b01973f9df9004ef17cd0c Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Wed, 11 Nov 2015 01:15:50 +0300 Subject: [PATCH 13/25] actions expreriments --- Tablet/Tablet.swift | 73 +++++++++++++++--- .../UserInterfaceState.xcuserstate | Bin 21145 -> 22974 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 5 ++ TabletDemo/TabletDemo/ViewController.swift | 6 +- 4 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 TabletDemo/TabletDemo.xcodeproj/xcuserdata/maxsokolov.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist diff --git a/Tablet/Tablet.swift b/Tablet/Tablet.swift index f6cd97f..8209a5b 100644 --- a/Tablet/Tablet.swift +++ b/Tablet/Tablet.swift @@ -34,8 +34,6 @@ public enum ActionType : String { case configure = "_configure" case willDisplay = "_willDisplay" case shouldHighlight = "_shouldHighlight" - - } public struct ActionData { @@ -54,13 +52,39 @@ public struct ActionData { } } +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 + } + } +} + +/** + A custom action that you can trigger from your cell. + You can eacily catch actions using a chaining manner with your row builder. +*/ public class Action { + /// The cell that triggers an action. public let cell: UITableViewCell + + /// The action unique key. public let key: String + + /// The custom user info. public let userInfo: [NSObject: AnyObject]? public init(key: String, sender: UITableViewCell, userInfo: [NSObject: AnyObject]? = nil) { + self.key = key self.cell = sender self.userInfo = userInfo @@ -72,6 +96,11 @@ public class Action { } } +public class ActionObject { + + +} + /** If you want to delegate your cell configuration logic to cell itself (with your view model or even model) than just provide an implementation of this protocol for your cell. Enjoy strong typisation. @@ -93,7 +122,7 @@ public protocol ReusableRowBuilder { var numberOfRows: Int { get } var reusableIdentifier: String { get } - func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> Bool + func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> ActionResult } /** @@ -167,15 +196,15 @@ public class TableRowBuilder : ReusableRowBuilder // MARK: Triggers - public func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> Bool { + 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 true + return .Failure } - return false + return .Failure } } @@ -192,7 +221,7 @@ public class TableConfigurableRowBuilder Bool { + public override func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> ActionResult { (cell as! C).configureWithItem(items[itemIndex]) @@ -259,7 +288,7 @@ public class TableSectionBuilder { } /** - A class that actualy handles table view's datasource and delegate. + Responsible for table view's datasource and delegate. */ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate { @@ -306,12 +335,17 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate return sections[indexPath.section].builderAtIndex(indexPath.row)! } - private func triggerAction(action: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath) -> Bool { + private func triggerAction(action: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath) -> ActionResult { let builder = builderAtIndexPath(indexPath) 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, @@ -383,11 +417,21 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { let cell = tableView.cellForRowAtIndexPath(indexPath) - if triggerAction(.click, cell: cell, indexPath: indexPath) { + + let a = triggerAction(.click, cell: cell, indexPath: indexPath) + switch a { + case .Success(let returnValue): + print(returnValue) + case .Failure: + print("") + } + + + /*if triggerAction(.click, cell: cell, indexPath: indexPath) { tableView.deselectRowAtIndexPath(indexPath, animated: true) } else { triggerAction(.select, cell: cell, indexPath: indexPath) - } + }*/ } public func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) { @@ -402,6 +446,11 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate public func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool { - return false + return true + } + + public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { + + return trigger() as! CGFloat } } \ No newline at end of file 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 daf4a1ae6ef4382ff03e0752c1edcbec2e236f3c..14c3ca349df8548a7d54b72f47381ddbe096e21a 100644 GIT binary patch literal 22974 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 diff --git a/TabletDemo/TabletDemo.xcodeproj/xcuserdata/maxsokolov.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/TabletDemo/TabletDemo.xcodeproj/xcuserdata/maxsokolov.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..fe2b454 --- /dev/null +++ b/TabletDemo/TabletDemo.xcodeproj/xcuserdata/maxsokolov.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/TabletDemo/TabletDemo/ViewController.swift b/TabletDemo/TabletDemo/ViewController.swift index ca9f5e8..73f99c6 100644 --- a/TabletDemo/TabletDemo/ViewController.swift +++ b/TabletDemo/TabletDemo/ViewController.swift @@ -17,10 +17,10 @@ class ViewController: UIViewController { super.viewDidLoad() tableDirector = TableDirector(tableView: tableView) - + let rowBuilder = TableRowBuilder(items: [1, 2, 3, 4], id: "cell") .action(.configure) { data in - + data.cell.textLabel?.text = "\(data.item)" } @@ -35,7 +35,7 @@ class ViewController: UIViewController { } .action(.shouldHighlight) { _ in - return false + return 90 } let sectionBuilder = TableSectionBuilder(headerTitle: "Tablet", footerTitle: "Deal with table view like a boss.", rowBuilders: [rowBuilder, configurableRowBuilder]) From 668a40dbba8eb400bfd9532d7f7874de4f9af38e Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Wed, 11 Nov 2015 23:04:52 +0300 Subject: [PATCH 14/25] various improvements --- Tablet/Tablet.swift | 57 +++++++++--------- .../UserInterfaceState.xcuserstate | Bin 22974 -> 22937 bytes TabletDemo/TabletDemo/ViewController.swift | 8 +-- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/Tablet/Tablet.swift b/Tablet/Tablet.swift index 8209a5b..33c9253 100644 --- a/Tablet/Tablet.swift +++ b/Tablet/Tablet.swift @@ -34,6 +34,7 @@ public enum ActionType : String { case configure = "_configure" case willDisplay = "_willDisplay" case shouldHighlight = "_shouldHighlight" + case height = "_height" } public struct ActionData { @@ -66,6 +67,15 @@ public enum ActionResult { return false } } + + public var returnValue: AnyObject? { + switch self { + case .Success(let returnValue): + return returnValue + case .Failure: + return nil + } + } } /** @@ -117,7 +127,7 @@ public protocol ConfigurableCell { A protocol that every row builder should follow. A certain section can only works with row builders that respect this protocol. */ -public protocol ReusableRowBuilder { +public protocol RowBuilder { var numberOfRows: Int { get } var reusableIdentifier: String { get } @@ -128,10 +138,12 @@ public protocol ReusableRowBuilder { /** A class that responsible for building cells of given type and passing items to them. */ -public class TableRowBuilder : ReusableRowBuilder { +public class TableRowBuilder : RowBuilder { + + public typealias ReturnValue = AnyObject public typealias TableRowBuilderActionBlock = (data: ActionData) -> Void - public typealias TableRowBuilderReturnValueActionBlock = (data: ActionData) -> AnyObject + public typealias TableRowBuilderReturnValueActionBlock = (data: ActionData) -> ReturnValue private var actions = Dictionary() private var items = [I]() @@ -188,12 +200,6 @@ public class TableRowBuilder : ReusableRowBuilder return self } - public func actionWithReturnValue(key: ActionType, action: (ActionData) -> Bool) -> Self { - - - return self - } - // MARK: Triggers public func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> ActionResult { @@ -234,7 +240,7 @@ public class TableConfigurableRowBuilder (ReusableRowBuilder, Int)? { + internal func builderAtIndex(var index: Int) -> (RowBuilder, Int)? { for builder in builders { if index < builder.numberOfRows { @@ -330,7 +336,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate - Returns: A touple - (builder, builderItemIndex) */ - private func builderAtIndexPath(indexPath: NSIndexPath) -> (ReusableRowBuilder, Int) { + private func builderAtIndexPath(indexPath: NSIndexPath) -> (RowBuilder, Int) { return sections[indexPath.section].builderAtIndex(indexPath.row)! } @@ -348,8 +354,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate internal func didReceiveAction(notification: NSNotification) { - if let action = notification.object as? Action, - indexPath = tableView.indexPathForCell(action.cell) { + 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) @@ -371,6 +376,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate 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) @@ -418,20 +424,11 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate let cell = tableView.cellForRowAtIndexPath(indexPath) - let a = triggerAction(.click, cell: cell, indexPath: indexPath) - switch a { - case .Success(let returnValue): - print(returnValue) - case .Failure: - print("") - } - - - /*if triggerAction(.click, cell: cell, indexPath: indexPath) { + if triggerAction(.click, cell: cell, indexPath: indexPath).isSuccess { tableView.deselectRowAtIndexPath(indexPath, animated: true) } else { triggerAction(.select, cell: cell, indexPath: indexPath) - }*/ + } } public func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) { @@ -440,17 +437,17 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate } 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 true + return triggerAction(.shouldHighlight, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath).returnValue as? Bool ?? true } - + public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { - return trigger() as! CGFloat + return triggerAction(.height, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath).returnValue as? CGFloat ?? tableView.rowHeight } } \ No newline at end of file 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 14c3ca349df8548a7d54b72f47381ddbe096e21a..e703eba5a373b116ab59d025e0486ecf495261a9 100644 GIT binary patch delta 10113 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 L(s}!<;Qs#rp^J2E delta 10145 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 diff --git a/TabletDemo/TabletDemo/ViewController.swift b/TabletDemo/TabletDemo/ViewController.swift index 73f99c6..60f6081 100644 --- a/TabletDemo/TabletDemo/ViewController.swift +++ b/TabletDemo/TabletDemo/ViewController.swift @@ -23,6 +23,10 @@ class ViewController: UIViewController { data.cell.textLabel?.text = "\(data.item)" } + .action(.shouldHighlight) { _ in + + return false + } let configurableRowBuilder = TableConfigurableRowBuilder(items: ["5", "6", "7", "8"]) .action(kConfigurableTableViewCellButtonClickedAction) { data in @@ -33,10 +37,6 @@ class ViewController: UIViewController { print("custom action indexPath: \(data.indexPath), item: \(data.item)") } - .action(.shouldHighlight) { _ in - - return 90 - } let sectionBuilder = TableSectionBuilder(headerTitle: "Tablet", footerTitle: "Deal with table view like a boss.", rowBuilders: [rowBuilder, configurableRowBuilder]) From 9c3a1ee5c996ed85902b2974fd90f8e122b0a647 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Thu, 12 Nov 2015 19:17:42 +0300 Subject: [PATCH 15/25] separate classes --- Tablet/TableRowBuilder.swift | 122 +++++++++++++ Tablet/TableSectionBuilder.swift | 76 ++++++++ Tablet/Tablet.swift | 162 ------------------ .../TabletDemo.xcodeproj/project.pbxproj | 8 + .../UserInterfaceState.xcuserstate | Bin 11439 -> 12583 bytes 5 files changed, 206 insertions(+), 162 deletions(-) create mode 100644 Tablet/TableRowBuilder.swift create mode 100644 Tablet/TableSectionBuilder.swift diff --git a/Tablet/TableRowBuilder.swift b/Tablet/TableRowBuilder.swift new file mode 100644 index 0000000..2be9c07 --- /dev/null +++ b/Tablet/TableRowBuilder.swift @@ -0,0 +1,122 @@ +// +// 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 building cells of given type and passing items to them. +*/ +public class TableRowBuilder : RowBuilder { + + public typealias ReturnValue = AnyObject + + public typealias TableRowBuilderActionBlock = (data: ActionData) -> Void + public typealias TableRowBuilderReturnValueActionBlock = (data: ActionData) -> ReturnValue + + private var actions = Dictionary() + private var items = [I]() + + public var reusableIdentifier: String + public var numberOfRows: Int { + get { + return items.count + } + } + + public init(item: I, id: String) { + + reusableIdentifier = id + items.append(item) + } + + public init(items: [I]? = nil, id: String) { + + reusableIdentifier = id + + if items != nil { + self.items.appendContentsOf(items!) + } + } + + public func appendItems(items: [I]) { + + self.items.appendContentsOf(items) + } + + public func clear() { + + items.removeAll() + } + + // MARK: Chaining actions + + public func action(key: String, action: TableRowBuilderActionBlock) -> Self { + + actions[key] = action + return self + } + + public func action(key: ActionType, action: TableRowBuilderActionBlock) -> Self { + + actions[key.rawValue] = action + return self + } + + public func action(key: ActionType, action: TableRowBuilderReturnValueActionBlock) -> Self { + + + 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 + } + return .Failure + } +} + +/** + Responsible for building configurable cells of given type and passing items to them. +*/ +public class TableConfigurableRowBuilder : TableRowBuilder { + + public init(item: I) { + super.init(item: item, id: C.reusableIdentifier()) + } + + 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 { + + (cell as! C).configureWithItem(items[itemIndex]) + + return super.triggerAction(key, cell: cell, indexPath: indexPath, itemIndex: itemIndex) + } +} diff --git a/Tablet/TableSectionBuilder.swift b/Tablet/TableSectionBuilder.swift new file mode 100644 index 0000000..ac58e38 --- /dev/null +++ b/Tablet/TableSectionBuilder.swift @@ -0,0 +1,76 @@ +// +// 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 building a certain table view section. +*/ +public class TableSectionBuilder { + + private var builders = [RowBuilder]() + + public var headerTitle: String? + public var footerTitle: String? + + public var headerView: UIView? + public var headerHeight: CGFloat = UITableViewAutomaticDimension + + public var footerView: UIView? + public var footerHeight: CGFloat = UITableViewAutomaticDimension + + /// A total number of rows in section of each row builder. + public var numberOfRowsInSection: Int { + + return builders.reduce(0) { $0 + $1.numberOfRows } + } + + public init(headerTitle: String? = nil, footerTitle: String? = nil, rowBuilders: [RowBuilder]? = nil) { + + self.headerTitle = headerTitle + self.footerTitle = footerTitle + + if let initialRows = rowBuilders { + self.builders.appendContentsOf(initialRows) + } + } + + public init(headerView: UIView? = nil, headerHeight: CGFloat = UITableViewAutomaticDimension, footerView: UIView? = nil, footerHeight: CGFloat = UITableViewAutomaticDimension) { + + self.headerView = headerView + self.headerHeight = headerHeight + + self.footerView = footerView + self.footerHeight = footerHeight + } + + internal func builderAtIndex(var index: Int) -> (RowBuilder, Int)? { + + for builder in builders { + if index < builder.numberOfRows { + return (builder, index) + } + index -= builder.numberOfRows + } + + return nil + } +} \ No newline at end of file diff --git a/Tablet/Tablet.swift b/Tablet/Tablet.swift index 33c9253..15d7bb9 100644 --- a/Tablet/Tablet.swift +++ b/Tablet/Tablet.swift @@ -106,11 +106,6 @@ public class Action { } } -public class ActionObject { - - -} - /** If you want to delegate your cell configuration logic to cell itself (with your view model or even model) than just provide an implementation of this protocol for your cell. Enjoy strong typisation. @@ -135,163 +130,6 @@ public protocol RowBuilder { func triggerAction(key: String, cell: UITableViewCell, indexPath: NSIndexPath, itemIndex: Int) -> ActionResult } -/** - A class that responsible for building cells of given type and passing items to them. -*/ -public class TableRowBuilder : RowBuilder { - - public typealias ReturnValue = AnyObject - - public typealias TableRowBuilderActionBlock = (data: ActionData) -> Void - public typealias TableRowBuilderReturnValueActionBlock = (data: ActionData) -> ReturnValue - - private var actions = Dictionary() - private var items = [I]() - - public var reusableIdentifier: String - public var numberOfRows: Int { - get { - return items.count - } - } - - public init(item: I, id: String) { - - reusableIdentifier = id - items.append(item) - } - - public init(items: [I]? = nil, id: String) { - - reusableIdentifier = id - - if items != nil { - self.items.appendContentsOf(items!) - } - } - - public func appendItems(items: [I]) { - - self.items.appendContentsOf(items) - } - - public func clear() { - - items.removeAll() - } - - // MARK: Chaining actions - - public func action(key: String, action: TableRowBuilderActionBlock) -> Self { - - actions[key] = action - return self - } - - public func action(key: ActionType, action: TableRowBuilderActionBlock) -> Self { - - actions[key.rawValue] = action - return self - } - - public func action(key: ActionType, action: TableRowBuilderReturnValueActionBlock) -> Self { - - - 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 - } - return .Failure - } -} - -/** - A class that responsible for building configurable cells of given type and passing items to them. -*/ -public class TableConfigurableRowBuilder : TableRowBuilder { - - public init(item: I) { - super.init(item: item, id: C.reusableIdentifier()) - } - - 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 { - - (cell as! C).configureWithItem(items[itemIndex]) - - return super.triggerAction(key, cell: cell, indexPath: indexPath, itemIndex: itemIndex) - } -} - -/** - A class that responsible for building a certain table view section. -*/ -public class TableSectionBuilder { - - private var builders = [RowBuilder]() - - public var headerTitle: String? - public var footerTitle: String? - - public var headerView: UIView? - public var headerHeight: CGFloat = UITableViewAutomaticDimension - - public var footerView: UIView? - public var footerHeight: CGFloat = UITableViewAutomaticDimension - - /// A total number of rows in section of each row builder. - public var numberOfRowsInSection: Int { - - var number = 0 - for builder in builders { - number += builder.numberOfRows - } - return number - } - - public init(headerTitle: String? = nil, footerTitle: String? = nil, rowBuilders: [RowBuilder]? = nil) { - - self.headerTitle = headerTitle - self.footerTitle = footerTitle - - if let initialRows = rowBuilders { - self.builders.appendContentsOf(initialRows) - } - } - - public init(headerView: UIView? = nil, headerHeight: CGFloat = UITableViewAutomaticDimension, footerView: UIView? = nil, footerHeight: CGFloat = UITableViewAutomaticDimension) { - - self.headerView = headerView - self.headerHeight = headerHeight - - self.footerView = footerView - self.footerHeight = footerHeight - } - - internal func builderAtIndex(var index: Int) -> (RowBuilder, Int)? { - - for builder in builders { - if index < builder.numberOfRows { - return (builder, index) - } - index -= builder.numberOfRows - } - - return nil - } -} /** Responsible for table view's datasource and delegate. diff --git a/TabletDemo/TabletDemo.xcodeproj/project.pbxproj b/TabletDemo/TabletDemo.xcodeproj/project.pbxproj index 3c3b98c..9f09f6c 100644 --- a/TabletDemo/TabletDemo.xcodeproj/project.pbxproj +++ b/TabletDemo/TabletDemo.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ 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 = (); }; }; 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 */; }; @@ -17,6 +19,8 @@ /* 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 = ""; }; 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 = ""; }; @@ -74,6 +78,8 @@ isa = PBXGroup; children = ( DAB7EB3D1BEF78A400D2AD5E /* Tablet.swift */, + 508B71831BF48DD300272920 /* TableSectionBuilder.swift */, + 508B71851BF48E0D00272920 /* TableRowBuilder.swift */, ); name = Tablet; path = ../Tablet; @@ -149,8 +155,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 508B71841BF48DD300272920 /* TableSectionBuilder.swift in Sources */, DAB7EB2D1BEF787300D2AD5E /* ViewController.swift in Sources */, DAB7EB3E1BEF78A400D2AD5E /* Tablet.swift in Sources */, + 508B71861BF48E0D00272920 /* TableRowBuilder.swift in Sources */, DAB7EB401BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift in Sources */, DAB7EB2B1BEF787300D2AD5E /* AppDelegate.swift in Sources */, ); diff --git a/TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/xcuserdata/max.xcuserdatad/UserInterfaceState.xcuserstate b/TabletDemo/TabletDemo.xcodeproj/project.xcworkspace/xcuserdata/max.xcuserdatad/UserInterfaceState.xcuserstate index 463604bc827b712334ee2b0e707fadcb314a5b97..72a945c6e7928014522f91d5773c547fb5e43747 100644 GIT binary patch delta 7108 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 Pss_p3s_*LmG2;IL3}IFD delta 6443 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 F|3B^)i46b% From f8c659f069fb3701ed2adbe1e68895aa34eab791 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Fri, 13 Nov 2015 01:00:12 +0300 Subject: [PATCH 16/25] ActionHandler approach --- Tablet/TableRowBuilder.swift | 65 ++++++++++-------- Tablet/Tablet.swift | 47 +++---------- .../UserInterfaceState.xcuserstate | Bin 22937 -> 19550 bytes TabletDemo/TabletDemo/ViewController.swift | 20 ++++-- 4 files changed, 58 insertions(+), 74 deletions(-) diff --git a/Tablet/TableRowBuilder.swift b/Tablet/TableRowBuilder.swift index 2be9c07..6c3a27c 100644 --- a/Tablet/TableRowBuilder.swift +++ b/Tablet/TableRowBuilder.swift @@ -21,17 +21,29 @@ import UIKit import Foundation +internal enum ActionHandler { + + case actionBlock((data: ActionData) -> Void) + case actionReturnBlock((data: ActionData) -> AnyObject) + + func call(data: ActionData) -> 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 : RowBuilder { - - public typealias ReturnValue = AnyObject - - public typealias TableRowBuilderActionBlock = (data: ActionData) -> Void - public typealias TableRowBuilderReturnValueActionBlock = (data: ActionData) -> ReturnValue - - private var actions = Dictionary() + + private var actions = Dictionary>() private var items = [I]() public var reusableIdentifier: String @@ -67,36 +79,33 @@ public class TableRowBuilder : RowBuilder { } // MARK: Chaining actions - - public func action(key: String, action: TableRowBuilderActionBlock) -> Self { - - actions[key] = action + + public func action(key: String, action: (data: ActionData) -> 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) -> 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) -> 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 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) } diff --git a/Tablet/Tablet.swift b/Tablet/Tablet.swift index 15d7bb9..00035e0 100644 --- a/Tablet/Tablet.swift +++ b/Tablet/Tablet.swift @@ -39,12 +39,12 @@ public enum ActionType : String { public struct ActionData { - 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 { } } -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 } } \ No newline at end of file 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 e703eba5a373b116ab59d025e0486ecf495261a9..4169e6efacb8dc7a04433b2f062c0fa4186df192 100644 GIT binary patch literal 19550 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 zareXBk97a0`?uu<(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(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)") } From 73ea2cf5730f055a3c1f474f149b1de6e51607b5 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Fri, 13 Nov 2015 01:24:24 +0300 Subject: [PATCH 17/25] 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]) From 2cb9078375b2d76165bb140393044d1fdb16392f Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sat, 14 Nov 2015 01:25:23 +0300 Subject: [PATCH 18/25] ActionType improved --- Tablet/TableDirector.swift | 10 ++--- Tablet/TableRowBuilder.swift | 28 +++++++------- Tablet/Tablet.swift | 35 ++++++++++++------ .../UserInterfaceState.xcuserstate | Bin 19785 -> 19633 bytes TabletDemo/TabletDemo/ViewController.swift | 2 +- 5 files changed, 44 insertions(+), 31 deletions(-) diff --git a/Tablet/TableDirector.swift b/Tablet/TableDirector.swift index 5e81f42..6c1eda9 100644 --- a/Tablet/TableDirector.swift +++ b/Tablet/TableDirector.swift @@ -25,7 +25,7 @@ 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]() @@ -72,7 +72,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate 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, cell: cell, indexPath: indexPath, itemIndex: builder.1) } internal func didReceiveAction(notification: NSNotification) { @@ -80,7 +80,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate 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) + builder.0.triggerAction(.custom(action.key), cell: action.cell, indexPath: indexPath, itemIndex: builder.1) } } @@ -102,7 +102,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate let cell = tableView.dequeueReusableCellWithIdentifier(builder.0.reusableIdentifier, forIndexPath: indexPath) - builder.0.triggerAction(ActionType.configure.rawValue, cell: cell, indexPath: indexPath, itemIndex: builder.1) + builder.0.triggerAction(.configure, cell: cell, indexPath: indexPath, itemIndex: builder.1) return cell } @@ -144,7 +144,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate // MARK: UITableViewDelegate - actions public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { - + let cell = tableView.cellForRowAtIndexPath(indexPath) if triggerAction(.click, cell: cell, indexPath: indexPath) != nil { diff --git a/Tablet/TableRowBuilder.swift b/Tablet/TableRowBuilder.swift index 6c3a27c..66a2924 100644 --- a/Tablet/TableRowBuilder.swift +++ b/Tablet/TableRowBuilder.swift @@ -21,12 +21,12 @@ import UIKit import Foundation -internal enum ActionHandler { +internal enum ActionHandler { - case actionBlock((data: ActionData) -> Void) - case actionReturnBlock((data: ActionData) -> AnyObject) + case actionBlock((data: ActionData) -> Void) + case actionReturnBlock((data: ActionData) -> AnyObject) - func call(data: ActionData) -> AnyObject { + func call(data: ActionData) -> AnyObject { switch (self) { case .actionBlock(let closure): @@ -67,6 +67,8 @@ public class TableRowBuilder : RowBuilder { self.items.appendContentsOf(items!) } } + + // MARK: Items manipulation public func appendItems(items: [I]) { @@ -86,23 +88,23 @@ public class TableRowBuilder : RowBuilder { return self } - public func action(key: ActionType, action: (data: ActionData) -> Void) -> Self { + public func action(actionType: ActionType, action: (data: ActionData) -> Void) -> Self { - actions[key.rawValue] = .actionBlock(action) + actions[actionType.key] = .actionBlock(action) return self } - public func action(key: ActionType, action: (data: ActionData) -> AnyObject) -> Self { + public func action(actionType: ActionType, action: (data: ActionData) -> AnyObject) -> Self { - actions[key.rawValue] = .actionReturnBlock(action) + actions[actionType.key] = .actionReturnBlock(action) return self } // MARK: Triggers - public func triggerAction(key: String, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? { + public func triggerAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? { - if let action = actions[key] { + if let action = actions[actionType.key] { return action.call(ActionData(cell: cell as? C, indexPath: indexPath, item: items[itemIndex], itemIndex: itemIndex)) } return nil @@ -122,10 +124,10 @@ public class TableConfigurableRowBuilder AnyObject? { - + public override func triggerAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? { + (cell as? C)?.configureWithItem(items[itemIndex]) - return super.triggerAction(key, cell: cell, indexPath: indexPath, itemIndex: itemIndex) + return super.triggerAction(actionType, cell: cell, indexPath: indexPath, itemIndex: itemIndex) } } diff --git a/Tablet/Tablet.swift b/Tablet/Tablet.swift index d9fbf9e..5c6f0ee 100644 --- a/Tablet/Tablet.swift +++ b/Tablet/Tablet.swift @@ -24,20 +24,31 @@ import Foundation internal let kActionPerformedNotificationKey = "_action" /** - Built in actions that Tablet provides. + The actions that Tablet provides. */ -public enum ActionType : String { +public enum ActionType { - case click = "_click" - case select = "_select" - case deselect = "_deselect" - case configure = "_configure" - case willDisplay = "_willDisplay" - case shouldHighlight = "_shouldHighlight" - case height = "_height" + case click + case select + case deselect + case configure + case willDisplay + case shouldHighlight + case height + case custom(String) + + var key: String { + + switch (self) { + case .custom(let str): + return str + default: + return "_\(self)" + } + } } -public struct ActionData { +public class ActionData { public let cell: C? public let item: I @@ -83,7 +94,7 @@ public class Action { /** If you want to delegate your cell configuration logic to cell itself (with your view model or even model) than - just provide an implementation of this protocol for your cell. Enjoy strong typisation. + just provide an implementation of this protocol for your cell. Enjoy safe-typisation. */ public protocol ConfigurableCell { @@ -102,5 +113,5 @@ public protocol RowBuilder { var numberOfRows: Int { get } var reusableIdentifier: String { get } - func triggerAction(key: String, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? + func triggerAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? } \ No newline at end of file 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 0a16516435f0dc4e8e84ace46b1e8ff879919f73..701e1e2e5e4ce2af9ff6030b4c9cfa109913a0c3 100644 GIT binary patch delta 10304 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 Af&c&j diff --git a/TabletDemo/TabletDemo/ViewController.swift b/TabletDemo/TabletDemo/ViewController.swift index 842f30e..fd74961 100644 --- a/TabletDemo/TabletDemo/ViewController.swift +++ b/TabletDemo/TabletDemo/ViewController.swift @@ -37,7 +37,7 @@ class ViewController: UIViewController { data.cell!.textLabel?.text = "" - print("custom action indexPath: \(data.indexPath), item: \(data.item)") + print("click action indexPath: \(data.indexPath), item: \(data.item)") } .action(kConfigurableTableViewCellButtonClickedAction) { data in From 20c19fda5019e37cbe86e7e52fe38f403d85bee2 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sat, 14 Nov 2015 01:43:43 +0300 Subject: [PATCH 19/25] bugfix for configureWithItem --- Tablet/TableDirector.swift | 4 ++-- Tablet/TableRowBuilder.swift | 19 ++++++++++-------- .../UserInterfaceState.xcuserstate | Bin 19633 -> 20028 bytes 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Tablet/TableDirector.swift b/Tablet/TableDirector.swift index 6c1eda9..2e8ed72 100644 --- a/Tablet/TableDirector.swift +++ b/Tablet/TableDirector.swift @@ -165,12 +165,12 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate } 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/TableRowBuilder.swift b/Tablet/TableRowBuilder.swift index 66a2924..a7f2044 100644 --- a/Tablet/TableRowBuilder.swift +++ b/Tablet/TableRowBuilder.swift @@ -82,21 +82,21 @@ public class TableRowBuilder : RowBuilder { // MARK: Chaining actions - public func action(key: String, action: (data: ActionData) -> Void) -> Self { + public func action(key: String, closure: (data: ActionData) -> Void) -> Self { - actions[key] = .actionBlock(action) + actions[key] = .actionBlock(closure) return self } - public func action(actionType: ActionType, action: (data: ActionData) -> Void) -> Self { + public func action(actionType: ActionType, closure: (data: ActionData) -> Void) -> Self { - actions[actionType.key] = .actionBlock(action) + actions[actionType.key] = .actionBlock(closure) return self } - public func action(actionType: ActionType, action: (data: ActionData) -> AnyObject) -> Self { + public func action(actionType: ActionType, closure: (data: ActionData) -> AnyObject) -> Self { - actions[actionType.key] = .actionReturnBlock(action) + actions[actionType.key] = .actionReturnBlock(closure) return self } @@ -126,8 +126,11 @@ public class TableConfigurableRowBuilder AnyObject? { - (cell as? C)?.configureWithItem(items[itemIndex]) - + switch actionType { + case .configure: + (cell as? C)?.configureWithItem(items[itemIndex]) + default: break + } return super.triggerAction(actionType, cell: cell, indexPath: indexPath, itemIndex: itemIndex) } } 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 701e1e2e5e4ce2af9ff6030b4c9cfa109913a0c3..3ddca07c471873da543d3a20d78336aa2dffdbd2 100644 GIT binary patch delta 10554 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 delta 10250 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 IpLLY~1Lzi1X#fBK From 6ee01134ff671487e7e9619287c6d0ca6ce1c2e9 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sat, 14 Nov 2015 17:49:30 +0300 Subject: [PATCH 20/25] estimatedRowHeight --- Tablet/TableDirector.swift | 28 ++++++++++----- Tablet/TableRowBuilder.swift | 29 ++++++++------- Tablet/Tablet.swift | 5 +-- .../TabletDemo.xcodeproj/project.pbxproj | 4 +++ .../UserInterfaceState.xcuserstate | Bin 20028 -> 24923 bytes .../TabletDemo/Base.lproj/Main.storyboard | 31 ++++++++++++---- .../ConfigurableTableViewCell.swift | 1 + .../TabletDemo/CustomTableActions.swift | 10 ++++++ TabletDemo/TabletDemo/ViewController.swift | 34 +++++++++++------- 9 files changed, 101 insertions(+), 41 deletions(-) create mode 100644 TabletDemo/TabletDemo/CustomTableActions.swift diff --git a/Tablet/TableDirector.swift b/Tablet/TableDirector.swift index 2e8ed72..8f2f74e 100644 --- a/Tablet/TableDirector.swift +++ b/Tablet/TableDirector.swift @@ -35,7 +35,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate self.tableView = tableView self.tableView.delegate = self self.tableView.dataSource = self - + NSNotificationCenter.defaultCenter().addObserver(self, selector: "didReceiveAction:", name: kActionPerformedNotificationKey, object: nil) } @@ -43,8 +43,8 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate NSNotificationCenter.defaultCenter().removeObserver(self) } - - // MARK: Public methods + + // MARK: Sections manipulation public func appendSection(section: TableSectionBuilder) { sections.append(section) @@ -69,7 +69,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate return sections[indexPath.section].builderAtIndex(indexPath.row)! } - private func triggerAction(action: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath) -> AnyObject? { + public func triggerAction(action: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath) -> AnyObject? { let builder = builderAtIndexPath(indexPath) return builder.0.triggerAction(action, cell: cell, indexPath: indexPath, itemIndex: builder.1) @@ -103,10 +103,13 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate let cell = tableView.dequeueReusableCellWithIdentifier(builder.0.reusableIdentifier, forIndexPath: indexPath) builder.0.triggerAction(.configure, cell: cell, indexPath: indexPath, itemIndex: builder.1) - + return cell } - +} + +extension TableDirector { + // MARK: UITableViewDataSource - section setup public func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { @@ -140,11 +143,14 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate return sections[section].footerHeight } +} + +extension TableDirector { // MARK: UITableViewDelegate - actions public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { - + let cell = tableView.cellForRowAtIndexPath(indexPath) if triggerAction(.click, cell: cell, indexPath: indexPath) != nil { @@ -169,8 +175,14 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate return triggerAction(.shouldHighlight, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? Bool ?? true } + public func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { + + return 300 + } + public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { - return triggerAction(.height, cell: nil, indexPath: indexPath) as? CGFloat ?? tableView.rowHeight + print(indexPath) + return triggerAction(.height, cell: nil, indexPath: indexPath) as? CGFloat ?? UITableViewAutomaticDimension } } \ No newline at end of file diff --git a/Tablet/TableRowBuilder.swift b/Tablet/TableRowBuilder.swift index a7f2044..c3cf2fd 100644 --- a/Tablet/TableRowBuilder.swift +++ b/Tablet/TableRowBuilder.swift @@ -21,12 +21,14 @@ import UIKit import Foundation +public typealias ReturnValue = AnyObject? + internal enum ActionHandler { case actionBlock((data: ActionData) -> Void) - case actionReturnBlock((data: ActionData) -> AnyObject) + case actionReturnBlock((data: ActionData) -> AnyObject?) - func call(data: ActionData) -> AnyObject { + func call(data: ActionData) -> AnyObject? { switch (self) { case .actionBlock(let closure): @@ -45,23 +47,26 @@ public class TableRowBuilder : RowBuilder { private var actions = Dictionary>() private var items = [I]() - + public var reusableIdentifier: String + public var estimatedRowHeight: Float public var numberOfRows: Int { get { return items.count } } - public init(item: I, id: String) { + public init(item: I, id: String, estimatedRowHeight: Float = 0) { reusableIdentifier = id + self.estimatedRowHeight = estimatedRowHeight items.append(item) } - public init(items: [I]? = nil, id: String) { - + public init(items: [I]? = nil, id: String, estimatedRowHeight: Float = 0) { + reusableIdentifier = id + self.estimatedRowHeight = estimatedRowHeight if items != nil { self.items.appendContentsOf(items!) @@ -94,7 +99,7 @@ public class TableRowBuilder : RowBuilder { return self } - public func action(actionType: ActionType, closure: (data: ActionData) -> AnyObject) -> Self { + public func action(actionType: ActionType, closure: (data: ActionData) -> ReturnValue) -> Self { actions[actionType.key] = .actionReturnBlock(closure) return self @@ -116,12 +121,12 @@ public class TableRowBuilder : RowBuilder { */ public class TableConfigurableRowBuilder : TableRowBuilder { - public init(item: I) { - super.init(item: item, id: C.reusableIdentifier()) + public init(item: I, estimatedRowHeight: Float = 0) { + super.init(item: item, id: C.reusableIdentifier(), estimatedRowHeight: estimatedRowHeight) } - - public init(items: [I]? = nil) { - super.init(items: items, id: C.reusableIdentifier()) + + public init(items: [I]? = nil, estimatedRowHeight: Float = 0) { + super.init(items: items, id: C.reusableIdentifier(), estimatedRowHeight: estimatedRowHeight) } public override func triggerAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? { diff --git a/Tablet/Tablet.swift b/Tablet/Tablet.swift index 5c6f0ee..64cfafa 100644 --- a/Tablet/Tablet.swift +++ b/Tablet/Tablet.swift @@ -40,8 +40,8 @@ public enum ActionType { var key: String { switch (self) { - case .custom(let str): - return str + case .custom(let key): + return key default: return "_\(self)" } @@ -112,6 +112,7 @@ public protocol RowBuilder { var numberOfRows: Int { get } var reusableIdentifier: String { get } + var estimatedRowHeight: Float { get } func triggerAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? } \ No newline at end of file diff --git a/TabletDemo/TabletDemo.xcodeproj/project.pbxproj b/TabletDemo/TabletDemo.xcodeproj/project.pbxproj index 42969fb..3a5cbf8 100644 --- a/TabletDemo/TabletDemo.xcodeproj/project.pbxproj +++ b/TabletDemo/TabletDemo.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 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 */; }; + DA1BCD111BF7388C00CC0479 /* CustomTableActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA1BCD101BF7388C00CC0479 /* CustomTableActions.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 */; }; @@ -23,6 +24,7 @@ 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 = ""; }; + DA1BCD101BF7388C00CC0479 /* CustomTableActions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomTableActions.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 = ""; }; @@ -68,6 +70,7 @@ DAB7EB2A1BEF787300D2AD5E /* AppDelegate.swift */, DAB7EB2C1BEF787300D2AD5E /* ViewController.swift */, DAB7EB3F1BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift */, + DA1BCD101BF7388C00CC0479 /* CustomTableActions.swift */, DAB7EB2E1BEF787300D2AD5E /* Main.storyboard */, DAB7EB311BEF787300D2AD5E /* Assets.xcassets */, DAB7EB331BEF787300D2AD5E /* LaunchScreen.storyboard */, @@ -165,6 +168,7 @@ DA1BCD0F1BF5472C00CC0479 /* TableDirector.swift in Sources */, DAB7EB401BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift in Sources */, DAB7EB2B1BEF787300D2AD5E /* AppDelegate.swift in Sources */, + DA1BCD111BF7388C00CC0479 /* CustomTableActions.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 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 3ddca07c471873da543d3a20d78336aa2dffdbd2..6c57e1d730bc92263b02d50902a776224ae6f460 100644 GIT binary patch literal 24923 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 a-Wzp%)c2##cru@q^po!%koZKS&iy}4qridy delta 11633 zcmahv2V9d!`*-)=8)isILc$Dzgak+s0+|pcC~id*_d<}UD1rr?)aG7CwYJW%AO@AoG^llQ&n?zv|_&pqdrZ{Syp;fxT>>&WZm z3T~rzt_y~@fe-KnVjuw_Km+1I0!Rc}paV&u5l99tK`YQ2v;l2FJJ25FfDRxRbOfD1 z9w-Kb!4OaahJsR128Mz6Ksgu#J_IwsOfU~D0ZYNBU^!R?CW6&q9as-Gfo)(r_!@iz z4uYfLBsdE$0q13K9ozsvgI~aX@BsV%_#P~W6>tQ6AC86N;1u{V z`~*&g)8Je<56*{+oUj_!z~yia{2XqC+u;uQ72F5+!vpXbJPj|w%kT=k1#iRO;A8j% zK84TV@5l%FB0uDh0#G30BQcVoa1?>!kQ!-FJZgjtC>_~R3)BYnMtx9Ul#lwM0#u0l zqXB3j8i_`s(P#{+Lhqxo$oVn)1WiTL&~!8d%|vt2JTxCIM$6E0v;wU~8__1T1#Ly! z&`$I<`UdSq`_O)L09{4jp=;=SbRFG5H_S^bq}qo}#}P$oMh-OaLQh zBuoes#mE^oqhaEi1SW~eWb8~9)0An(WILJWObaHL>Bw|q@|a#sKGTmWVjN5bQ^^cx zMld6pQOsy&3_}=>8OKaxrZY2`nanK4#mr{rGYgm{%xY!>vy0iy>|wrP4lpN}Gt61$ z0&|hM&D>#rVD2(MG7p%?%wNpk%nRlp<|X#QzSs}*u^3Bm2zEwcIgZ8(9D~(35vSt} zY{QLl6P$_dI19JL?Qmz@1$V`LaX#*ci|`;k6qn)=cqAT$N8>U01H2e7!_~MRFUPC! zYP=4w$D8pNcpKi1zs9@pUc3(Hi#9lLN=Hcv2r$=Rj@H^65EJPW;0kD+n8<5wqe_{?bz;Y54I;e zfE~yVVk_C<>;v{8`-uIO{fqsZeZl_2^X2*R{CNSq z5T2A5&Xe;R@sfEdJUtlCOXZn(R$e+UgO|x`$IEryp%NrdNmrMKEmwsC6;P2t!Y5A% zB0LgCKZSi;XE*OwTv}8%vPF5pP>1UV8>KRtt@@@0y(KBl)Xbb@$hPW}EUA{%BxBR; z=5!>*l$~vI?PS$16>q8YEbs&VAONI*44_^G^dJ?a0Ru1s6EFh{u!3|FLr)aS5y|1R(e4d z?FvSh4X?}>hPX~zLmYk$RCfk_fqEtA0=j~3pgZURdV*e{H|RqmNF<3OauQ7xB!)PUNas{SPf6&0n_gt~hl9Tl$KvS_vj)PZ{U zQ&IPvybgtf9sMgCwpc+WxtKJf($jUN3NCTHhOF^G^lnH`FC^PBw9LEN2C%VPPF_}d zdBNx!umRMc1)C|kUw|*c7BJEk6)N*J5F-Kk!nUp%=|cwd*Nx+I1>IgXyYz`k)SLu)K5NJWyAIZ;7oMTp*1}p$kUEw`_o3 z0pGcyS4opiXVQsYZQ@PNBD$Q^)%DtTLpgq|!I@SdaK%42ccfQi(Gp%&_366ryDl3xE|!^G*a*?%#*S3}U^ zv9{j-VQuf&6?tV-iIwHWZU@ftkQtw!-rrGDl1{^?V^nTI<)HN9O2<%-qogO~3)S8G zmlZi0xeh191j1$@0A_=cum$+i#f8Zf1;pTGyftjoB`2>-r*<{4HK_NFwS(WWx`xiL{h2yRaH?*ri|4os`PpbeYEKHW5>QyGVBa{0CgSg0=vR)usaz* z29iOfxDNJ&y}%;ahYTjes29Iam06^2oCu3xv3t4$4uAvUATorMkfEfsj)vssu!JUz z&QvgE?o{DAsU8{UC8iS0UH00l;7B-{8Y>({-m8XVNI9M9^bJdaA3&}KIw2tyWE81t zpl&?;5Qu8v1UQjYlHoOQ5}Zs%kdf3@f>UCg-P<_^cp{_HJ}w@({~Fd!hqK;U=Yq4z zXflR$?a`@t;Gl*z>pg3{Qd|HR_RYy_KfKZ%TRZ`y7B29H439U!#c-*c?j>YwHBCM= z)#SVW)`TlzEvy6TWy?rm!`>_4O83Oi2&smv2lLcfUS+pDh1Q7zw5T;3WF{veW)apKSr&HHd z{|zD(goHp;jRa&#H3}w6saSFY!aAW4B%@+MQu1jv3MEuuZzYRYETTxH0P0#41y-PF zQcbf>O)ZLce@Knz^Y)rt*HnS5p`bwtNc(zI9jPZ>8&D=A{p)R0$@14`f{e&a0bm7b zRE;cT#T!5dYU~CqB#G6YjT;OLWua!T_sAwI-Fpo2*d}U;TD@a~s4dE)p&PYB?NJWu zfO1hs)QPMnYslwhEm=p_lMO3SXIh^$11i+r@+u1|9j==}Ca1h%YM!HnmK%;DZ>>m!fQRY6DWl8-3R6rblcC6w zn&M@17MfFoTxd4gOZJidZ`o14Q1GS#QN+b5^q$~?7NCVRU%d)0d5+3jI<~GdFVuT;1*QBQVjDFd<>)`$of4au zjwmiKD;-MfvFx&;v=;Dg@fny~hgPChXf;|xj*w&IBypa8odMB0cNIsDdW*L1sR|D( z*~R5lEM?`5Jb}?&hQ@bk?SZ(Tb&5d_cR;1G?Nl~0tJ0Is+{sOmuE@!I{g$9eYNBY? zvPDT*K||SwHlr`-ZbOcf6GYd&^B}jL6nY_km1og*Po6#XUwPJ3aH3rv=ovROUnsW~ zxl3h5g@cyyWu=M%W#wMlE8T@)6S4E9_s{LHOhcsEEf97>2hnL-(4#}>Fgk*cqGRYd zI)P52Q{)1{_dU+y9e?!J_+!s=gAYAJf6!>)Ntft3 zx%(=bqrV|ni(a6A&`a_o`I$U;9nl%&WZ1XkG{a+j$UX8C>FV|AhO?080Hm}Jv%e1A zlvpN^5xlcl$OMyL$bHiF-Gh_TK5N)J>!eIr!@8#KOwEMTT_3*LwM%6&J;f9|D%_`* zSG+ONOe|2>FbXDy{7QbSaXYlfl?z>FQB#=hT4v4e>yZyb%eHC|N{^up#VON>G0_Oe zBr_?Do=IiW7z1M@&&coO5AvM+N&X^#uK+5>!dRJfCWEmtjVb0A9Q>Sv>pA!}2d{JR z2Gy4%ewUhQ$+V?mpJ~OkX4;T{$V(1_TBaS-p2^`LVp zGk__f(T*9&3}T9z!ORd2`f$*fgMJ+J=U_lREMZESGG-X_9x3BsAP4yz4B}`(UFez+ z`>}7gBFBJ&;U$%>liC;wQ^ky>R>Qo{K|wY10SAS2R*o`BKc1OP%Qt2MGm-g_nZ!X6 z2gMwea4@8f`G}dqe9U~pK`94i91P`PI9=64*WIbieB@C!poO^6s8gg_^$05vT%*t0h25>NvD}Yh2vm>*H zS^J-yHEg$$+3LpbX6}o(*^_%Ytfw4qXLe9I?)2~&%|V5Gn;6RFab;Nl-n2Y68gvTU z$S{pnW?uKQ+<<&9v+rGA4l+mFmT-tU%t0jw<7$|r%rOpXIGFXWC7kxES(PueQ%i_( zy-10cylpAxy>PW_nW2-dVY^GrHMgQJGgp|a%y%4&=U@T{6FI1@W4>puGdGx<9Mo~p z$Uzea?d}RH-o+)0T>;6pIm|tV)?ePB!TiF}vyQh0WFFEQka@)X%E3k)OnVbEo-n^t z?`57c&p4RO!IT>259T=s^&Cv~l-gY*0cPHvfx2UsY~rASP8gq}GWt_Xz*Jpkl6npY z(IYlJXk!5u;$ST5QQ^t0G&XZEor6{mS~!@QFU)!+4}Fvrhf!f-8Kzd3!9iOM4#yE3 zY|OzXR6A|;DL%AyfMc=JwNkI}sl_TBM^DHr^^JRC4UT_DF<6UJY1M&sI0-kx$v6d5 zHkxv<83(gD*qnncIM{MIPQwOl#3pRUl$KT;Y|X)34tC^VCl2;>i!;e1&b6t&n|h^+ zVLRLuXS-$UF6%MH(&m*+aVsiQ+#0vxU|SC6yp}0$k8>L$qB|hsj+kO@$HDegV85jq zB5*g{^X&=nJnl_C=3oa3Z)S*d;sRXgWy})-vBNFk0UXSGTfoJ5FmoPLFYdy@&Ky)z zu`086JX^T8)qu0FObM6aa<^=U;rBS$m4n@Ca0Ra9V0RAoAcfs>%gfwtmag8;*PB|# zm1>N2;wt?9yTWzisX+ZXCYZzH@OV4{PsAVMNq92;2v5Nu<4-u)n}dBh*pGvS94z7> zrFakr2XnB5gH-*)I9SfX%FppMJRQ%#Gx03!!n5%lJQvTy^YH?_kb@&QNJG{*YJ5{T zIE{ldIXIhx^EtSPgG)JB&B1yOu6)PI@TXoU>f>5$>*tzeij}^Jv$)O+%g-0~@Py*6 zqL8=3Fka~e7i?N)?f~Cjx7G{j|E4=6dwbm`FW5o1EO7Nmk9ixm)e9Tw;uHhlc6Pke z3n+FC&meE_^^JFYNWO5a>r

)y&r7ZF~p4;GwSQ+@5cbAM=ivQ5wd*J^m`@yywz4 zZvXc9t5{Rvn%Vdr{8zkqhSL~ip}><#YxouoMfiJs9pAt=IXIGoqc}L4 zgJbIOZF~nb!*@AY#liOpwZO5|U1=M~)xj=z;$QJIy7Ip|Klpe22VM0i2b~-w?p5@V z>^9rQ8z%m|qKCU%p*N+bjO|`!NwK&)7q2Xt1uRSPv5-Y9!(tAO=imemPUPT+bu5qd z0nJ#NEGKcaM?i6Yggm6wI9V|p`fp^gVQe^E63Id8b)UGGO!bmMJ5Zg@zte$ws{z$O zODwDTUs7S?*#xgtrgLzHPlH(G&BC2*3TymVT1>3jyJQvzU9VPnJUJkwacXzBNX%)L z*MexmHv3mB*(^Oyu`M|`hl6w7Smt>-TG~5#!?eCtdKWJ{+R3(OJN-}6^VrT_Iu>wn z;Tt-hX0^LIexy4?rqJRxHN|XxO-nDf-@npQz!rKjE#_#`gwjGy!_AR%k$>83y@#b# zqv180Vz%^u5>>_y^P>8cgUjBadYUrm$=Vo?y`b%SWi%LR!|{#jeaL?NuQ)$pr&63$&&xTu!j1B? zS15hY7QgVCvelGI5$e+nW)DKA*R9w&?81M=xQJa$G154%5$Tej!WK6@VRMV1b9hj*HaJ?EkZLtevv z0Ysm%pR;S(b?ka}1G|yk#BS!`1`clIAkFaf`3nwy$-ylg-1-^&rMqpwZezEzJJ_#) zii6u|WlhQ4&cPiV{ECA+>3i2r3tEK0c=k9;4_LMA3HBs=ii5j2xSNA}YS}aFS@s+U zzv1Bb96V0_^nA;b4(w&f)w5UFtL%5|HI@SQa_|TTPjK)I2hYDwtn5wp2RF`J>}~cA z2lsJsKL-!gvUk}Z*?Sy3$iYJ#JWO%UY*io6{>IV}^xuDwzE@uGQZTGFt$crm^o)6_0R~pXTN9I=dcrlsN-v zi7BVozJbJU`V8|a_o?(5 z;WNr-jL%e`={_@kTt0Jr=J_n}S>&_C=To0*pEW-Fea`y)G#m@Pk-Q#{INgJU+%B)Pw+SRH}>!CU*J#tKk}dJ zKi_|$|6>1I|MmVG{Wtr6>A%PSi2oV?3;wtLANl|3|F{1?0U#hJpj*JufbxLJ0W$-> z3fL3yOCTHQ6X@p*3<%^0N&~|JBLbrW)q%NzT>_nflLOZVZVJ2<_(R~mz@Gyj1U?G< zjUUd}@DuquellOrPvcwo&H3&4Is9CHCw>opFMc0>KEHrJm0!=_$v?n9%s?W46eJ0f204{M$w6&``UZ^&njcgbv_0rx z(5av^LFaQoL@-(~Mlew@O|VF?Oz?$Zi(s2z zhhV2*m*9}#q~NsRtl(S01;K5>4}u>BKM8&pJQw^Wcp>x`1`30OLSck3UYID<2^$G} z2`30=3Kuwq^}-dxmBQ7+&BE=%UBW}cYr;Fi2f|;4kA+Wz`N84A%HX(QO>jc6HrNns z3bq8N2it<11h)*%4;~y`8O#Mw3H~H_TJVhES;32fmjr(rTpe5+TpzqQ__~M@MT+7? zYEit%D6)vsMU6$7qAXDtQD0GikwY|4R4f`Ha#o4PikzYeq7OxrMN>rcMXN=dMLR`D zL?=b3MQ249MVCcaMb|_>ihdRSDfSZ!#Zh8~I941d)`%0tjm2%mZN=@xIpSX8zT$r3 z{$huCptwprLHv>UWARk+bn#+wwYXMXFJ2{HBVH?BFWxTRD?TOuR(wHxNqkLwU3}9i zzAb(xeklo*2qeK0i9{+1mBdKYl6Xm?L?^LInn>)DrjnMD){?f8_L3Y)H%XDCSTaO1 zR8lUfl#Gy!l5mn~k_D1Qk|mN)CDoEz$y&*J$wtX$$(NF?lI@c3BrifDLsCL=L;8da z4k-yK4H*_v9#R=HB4m8X#E?lL&W}Pq4w)Jy=79tCkh0CI3(Xtp>Bbi>7CNs$_vUFKXSsSOUoveebqbyI> zPgWo+loiR|lM&fC*#y~#vdOY3vQK2wWJ_e9%Bp3xvU=GH*-F`J+2^v|vYVlPp-G`_ zLQ6wuhb{?S8oDgBI&^L5j?kT1tD5io*@U?Z#%O(WVyw2$Zz z(J>+~qDw?!L{Y?mh(Qs1BThw}i8vQ=KH~d`8xap89!2~X@g(A9WME`aq|g~DicE{N zMdn40h#Vg|H*$XD!pOyuOCy&>)K!#IYHCzn)aOxaqt-`li`pLbRn-2d15t;fPDh=IIv4d_)U~MV zQTL-BMg11_H0t-L=W-w6q5N98N4Zyd zLU~#FL=~Y@sghL|RfejG%C2gw>aOac>Z$6jDppmhMykfB#;S;FylR?ihRUUyt6HF1 ztXisCty-(vpxUh3qS~f9pgOHOr@ElJtolxMUG=l-f$CS)6V)@-bJbtYI7wVgTwP&Sjbz60gx}&#-eGiX`^Yc$<=hx zbl3FK^wA8_e4we(I9F@7YIbUNYxZgmX^v=)Yffq|YVK>EX`XBT*8CGMh!2a8jE|0w zjgN~jjxUdQ#!rZ!6h9??di<>TIq~!2m&Vt}Z;#&}e4xY^b?@mab<=gTbaQm`b&GUM zb=A5$-3r|*-RHXXx=p$-bz61&bq95ab;pw0C-qF~ozyp}AZcgPk)&fuCz4JlMsZTEKOOKQsYdi*Q@k;eVX2=x9GR(_v;Vp z59^Pm#-*mF8d6QE*3|8(2U8EH9!))w7M`X_OGwkEHA<^UBWdH(CZtVDyOj1r+QYQp z(w?UMk@lAX8+;7@hCqYB5NyyH@(cxrj|{U6iw(7g^@eSR9fqBTU4}h|BZlLKQ-(8! zZw(g=&g+Js43CY#=w}Qx3XCFSh*55gF{+GeV}em@Y+)Q~tTNUb*BG}O4;arHuNtoz zuN!X~ZyWC$9~mDTpBn!#{%K-NLQ{k(-lR7fOlDKMsj;brskNz{DaX{&lxON~8epn0 zy>I%!L`>sM6HHT0GfXbi9MgQ$LQ}2Nw8pf}^o?ns>452w>4@p9>AdNZ>5A!^>ALBj z=?^nD2b;sqQD%i%X;zz)&8cRi*=$ZX+sw_)oy_^>LFU2c5_73}n0d7MeY4ZdnJ1V( zG*36rH`kljnm3p?o41&^oA;Uzm=BwenopQdnJ<}dnID;-oBuMuFu$}op~c_Aw+JmF zONd2gQCM^qlckxZoh8STYw2X^Z0Td^XX$ToSO!@JTPiGLEt4#>ElVt)TB0Y%Q^luyWRg)(zGJ)+^S>>4E7n>4oXV>BG{;q)$qpmOe9m zcKW>ZrRmk_b?Gb8SEgT0|2;#P5tgCK&}1ZLBxR&zq-7X0nr5`lXqV9;qf_Qvu(6}VcTN++IG-(GSiT0&a`LdWOm8y zomreYB6D=+`@DrN_U`rqdy##p zz0y9~KDo1firr - + - + @@ -49,24 +49,41 @@ - + - - + + + + + + + diff --git a/TabletDemo/TabletDemo/ConfigurableTableViewCell.swift b/TabletDemo/TabletDemo/ConfigurableTableViewCell.swift index 3d96de5..a83405f 100644 --- a/TabletDemo/TabletDemo/ConfigurableTableViewCell.swift +++ b/TabletDemo/TabletDemo/ConfigurableTableViewCell.swift @@ -15,6 +15,7 @@ class ConfigurableTableViewCell: UITableViewCell, ConfigurableCell { typealias Item = String @IBOutlet weak var button: UIButton! + @IBOutlet weak var contentLabel: UILabel! static func reusableIdentifier() -> String { diff --git a/TabletDemo/TabletDemo/CustomTableActions.swift b/TabletDemo/TabletDemo/CustomTableActions.swift new file mode 100644 index 0000000..3c55cd9 --- /dev/null +++ b/TabletDemo/TabletDemo/CustomTableActions.swift @@ -0,0 +1,10 @@ +// +// CustomTableActions.swift +// TabletDemo +// +// Created by Max Sokolov on 14/11/15. +// Copyright © 2015 Tablet. All rights reserved. +// + +import UIKit +import Foundation diff --git a/TabletDemo/TabletDemo/ViewController.swift b/TabletDemo/TabletDemo/ViewController.swift index fd74961..9b0aa9b 100644 --- a/TabletDemo/TabletDemo/ViewController.swift +++ b/TabletDemo/TabletDemo/ViewController.swift @@ -23,29 +23,39 @@ class ViewController: UIViewController { data.cell?.textLabel?.text = "\(data.item)" } - .action(.height) { data in - - return 50 - } .action(.shouldHighlight) { data in return false } - let configurableRowBuilder = TableConfigurableRowBuilder(items: ["5", "6", "7", "8"]) + let configurableRowBuilder = TableConfigurableRowBuilder(items: ["5", "6", "7", "8"], estimatedRowHeight: 300) .action(.click) { data -> Void in - - data.cell!.textLabel?.text = "" - + print("click action indexPath: \(data.indexPath), item: \(data.item)") } - .action(kConfigurableTableViewCellButtonClickedAction) { data in + .action(kConfigurableTableViewCellButtonClickedAction) { data -> Void 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]) + .action(.height) { data -> ReturnValue in + + if data.item == "5" { + return 70 + } + return nil + } + .action(.configure) { (data) -> Void in + + data.cell!.contentLabel.text = "With iOS 8, Apple has internalized much of the work that previously had to be implemented by you prior to iOS 8. In order to allow the self-sizing cell mechanism to work, you must first set the rowHeight property on the table view to the constant UITableViewAutomaticDimension. Then, you simply need to enable row height estimation by setting the table view's estimatedRowHeight property to a nonzero value, for example" + + //data.cell!.setNeedsUpdateConstraints() + //data.cell!.updateConstraintsIfNeeded() + } + + let sectionBuilder = TableSectionBuilder(headerTitle: "Tablet", footerTitle: "Deal with table view like a boss.", rowBuilders: [configurableRowBuilder]) tableDirector.appendSection(sectionBuilder) } -} \ No newline at end of file +} + +// вход со стороны кутузовского проспекта между домами 10 14 левее чайхоны, на охране сказать кодовое слово Магия - найти клуб лабиринт \ No newline at end of file From c8333322cc283902bd2033b6e7c67233b5cd3274 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 15 Nov 2015 13:44:05 +0300 Subject: [PATCH 21/25] implemented estimatedRowHeight --- Tablet/TableDirector.swift | 24 +++++++++--------- Tablet/TableRowBuilder.swift | 10 ++++---- Tablet/Tablet.swift | 2 +- .../TabletDemo.xcodeproj/project.pbxproj | 7 +++++ .../UserInterfaceState.xcuserstate | Bin 24923 -> 26363 bytes TabletDemo/TabletDemo/ViewController.swift | 11 +++----- 6 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Tablet/TableDirector.swift b/Tablet/TableDirector.swift index 8f2f74e..b8bb781 100644 --- a/Tablet/TableDirector.swift +++ b/Tablet/TableDirector.swift @@ -146,8 +146,19 @@ extension TableDirector { } extension TableDirector { - + // MARK: UITableViewDelegate - actions + + public func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { + + return builderAtIndexPath(indexPath).0.estimatedRowHeight + } + + public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { + + + return triggerAction(.height, cell: nil, indexPath: indexPath) as? CGFloat ?? UITableViewAutomaticDimension + } public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { @@ -174,15 +185,4 @@ extension TableDirector { return triggerAction(.shouldHighlight, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? Bool ?? true } - - public func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { - - return 300 - } - - public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { - - print(indexPath) - return triggerAction(.height, cell: nil, indexPath: indexPath) as? CGFloat ?? UITableViewAutomaticDimension - } } \ No newline at end of file diff --git a/Tablet/TableRowBuilder.swift b/Tablet/TableRowBuilder.swift index c3cf2fd..a09de24 100644 --- a/Tablet/TableRowBuilder.swift +++ b/Tablet/TableRowBuilder.swift @@ -49,21 +49,21 @@ public class TableRowBuilder : RowBuilder { private var items = [I]() public var reusableIdentifier: String - public var estimatedRowHeight: Float + public var estimatedRowHeight: CGFloat public var numberOfRows: Int { get { return items.count } } - public init(item: I, id: String, estimatedRowHeight: Float = 0) { + public init(item: I, id: String, estimatedRowHeight: CGFloat = UITableViewAutomaticDimension) { reusableIdentifier = id self.estimatedRowHeight = estimatedRowHeight items.append(item) } - public init(items: [I]? = nil, id: String, estimatedRowHeight: Float = 0) { + public init(items: [I]? = nil, id: String, estimatedRowHeight: CGFloat = UITableViewAutomaticDimension) { reusableIdentifier = id self.estimatedRowHeight = estimatedRowHeight @@ -121,11 +121,11 @@ public class TableRowBuilder : RowBuilder { */ public class TableConfigurableRowBuilder : TableRowBuilder { - public init(item: I, estimatedRowHeight: Float = 0) { + public init(item: I, estimatedRowHeight: CGFloat = UITableViewAutomaticDimension) { super.init(item: item, id: C.reusableIdentifier(), estimatedRowHeight: estimatedRowHeight) } - public init(items: [I]? = nil, estimatedRowHeight: Float = 0) { + public init(items: [I]? = nil, estimatedRowHeight: CGFloat = UITableViewAutomaticDimension) { super.init(items: items, id: C.reusableIdentifier(), estimatedRowHeight: estimatedRowHeight) } diff --git a/Tablet/Tablet.swift b/Tablet/Tablet.swift index 64cfafa..6ceeeaf 100644 --- a/Tablet/Tablet.swift +++ b/Tablet/Tablet.swift @@ -112,7 +112,7 @@ public protocol RowBuilder { var numberOfRows: Int { get } var reusableIdentifier: String { get } - var estimatedRowHeight: Float { get } + var estimatedRowHeight: CGFloat { get } func triggerAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? } \ No newline at end of file diff --git a/TabletDemo/TabletDemo.xcodeproj/project.pbxproj b/TabletDemo/TabletDemo.xcodeproj/project.pbxproj index 3a5cbf8..f241c66 100644 --- a/TabletDemo/TabletDemo.xcodeproj/project.pbxproj +++ b/TabletDemo/TabletDemo.xcodeproj/project.pbxproj @@ -122,6 +122,7 @@ TargetAttributes = { DAB7EB261BEF787300D2AD5E = { CreatedOnToolsVersion = 7.0.1; + DevelopmentTeam = Z48R734SJX; }; }; }; @@ -279,11 +280,14 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = TabletDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.tablet.TabletDemo; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; }; name = Debug; }; @@ -291,11 +295,14 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = TabletDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.tablet.TabletDemo; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; }; name = Release; }; 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 6c57e1d730bc92263b02d50902a776224ae6f460..61803cb7d4ddd5ef8ce9bdf7b59a32f84095fc17 100644 GIT binary patch delta 14504 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 Void in - + data.cell!.contentLabel.text = "With iOS 8, Apple has internalized much of the work that previously had to be implemented by you prior to iOS 8. In order to allow the self-sizing cell mechanism to work, you must first set the rowHeight property on the table view to the constant UITableViewAutomaticDimension. Then, you simply need to enable row height estimation by setting the table view's estimatedRowHeight property to a nonzero value, for example" - - //data.cell!.setNeedsUpdateConstraints() - //data.cell!.updateConstraintsIfNeeded() } - let sectionBuilder = TableSectionBuilder(headerTitle: "Tablet", footerTitle: "Deal with table view like a boss.", rowBuilders: [configurableRowBuilder]) + let sectionBuilder = TableSectionBuilder(headerTitle: "Tablet", footerTitle: "Deal with table view like a boss.", rowBuilders: [rowBuilder, configurableRowBuilder]) tableDirector.appendSection(sectionBuilder) } -} - -// вход со стороны кутузовского проспекта между домами 10 14 левее чайхоны, на охране сказать кодовое слово Магия - найти клуб лабиринт \ No newline at end of file +} \ No newline at end of file From d844a753602efe2e74b5295159d4ec694f10bd72 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 15 Nov 2015 16:12:33 +0300 Subject: [PATCH 22/25] readme updated --- README.md | 84 ++++++++++-------- .../UserInterfaceState.xcuserstate | Bin 26363 -> 26276 bytes 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index fd08b41..e047841 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,17 @@ ![Tablet](https://raw.githubusercontent.com/maxsokolov/tablet/assets/tablet.png) -Tablet is a super lightweight yet powerful generic library that handles a complexity of UITableView's datasource and delegate in a Swift environment. Tablet's goal is to provide an easiest way to create complex table views. With Tablet you don't have to write a messy code of switch or if statement when you deal with bunch of different cells in different sections. +Tablet is a super lightweight yet powerful generic library that handles a complexity of UITableView's datasource and delegate methods in a Swift environment. Tablet's goal is to provide an easiest way to create complex table views. With Tablet you don't have to write a messy code of switch or if statements when you deal with bunch of different cells in different sections. + +That's almost all you need in your controller to build a bunch of cells in a section: +```swift +TableConfigurableRowBuilder(items: ["1", "2", "3", "4", "5"], estimatedRowHeight: 42) +``` +Tablet respects cells reusability feature and it's type-safe. See the Usage section to learn more. ## Requirements - iOS 8.0+ -- Xcode 7.0+ +- Xcode 7.1+ ## Installation @@ -30,14 +36,16 @@ $ pod install ### Very basic +You may want to setup a very basic table view, without any custom cells. In that case simply use the `TableRowBuilder`. + ```swift import Tablet let rowBuilder = TableRowBuilder(items: [user1, user2, user3], id: "reusable_id") .action(.configure) { data in - data.cell.textLabel?.text = data.item.title - data.cell.detailTextLabel?.text = data.item.isActive ? "Active" : "Inactive" + data.cell?.textLabel?.text = data.item.username + data.cell?.detailTextLabel?.text = data.item.isActive ? "Active" : "Inactive" } let sectionBuilder = TableSectionBuilder(headerTitle: "Users", rowBuilders: [rowBuilder]) @@ -46,6 +54,40 @@ let director = TableDirector(tableView: tableView) director.appendSections(sectionBuilder) ``` +### Type-safe configurable cells + +Let's say you want to put your cell configuration logic into cell itself. Say you want to pass your view model (or even model) to your cell. +You could easily do this using the `TableConfigurableRowBuilder`. Your cell should respect the `ConfigurableCell` protocol as you may see in example below: + +```swift +import Tablet + +class MyTableViewCell : UITableViewCell, ConfigurableCell { + + typealias Item = User + + static func reusableIdentifier() -> String { + return "reusable_id" + } + + func configureWithItem(item: Item) { // item is user here + + textLabel?.text = item.username + detailTextLabel?.text = item.isActive ? "Active" : "Inactive" + } +} +``` +Once you've implemented the protocol, simply use the `TableConfigurableRowBuilder` to build cells: + +```swift +import Tablet + +let rowBuilder = TableConfigurableRowBuilder() +rowBuilder.appendItems(users) + +tableDirector.appendSection(TableSectionBuilder(rowBuilders: [rowBuilder])) +``` + ### Cell actions Tablet provides a chaining approach to handle actions from your cells: @@ -65,40 +107,6 @@ let rowBuilder = TableRowBuilder(items: [user1, user2, us } ``` -### Configurable cells - -Let's say you want to put your cell configuration logic into cell itself. Say you want to pass your view model (or even model) to your cell. -To provide this behaviour simply follow: - -```swift -import Tablet - -class UserTableViewCell : UITableViewCell, ConfigurableCell { - - typealias Item = User - - static func reusableIdentifier() -> String { - return "reusable_id" - } - - func configureWithItem(item: Item) { // item is user here - - textLabel?.text = item.title - detailTextLabel?.text = item.isActive ? "Active" : "Inactive" - } -} -``` -Once you follow the protocol, simply use TableConfigurableRowBuilder to build cells: - -```swift -import Tablet - -let rowBuilder = TableConfigurableRowBuilder() -rowBuilder.appendItems(users) - -tableDirector.appendSection(TableSectionBuilder(rowBuilders: [rowBuilder])) -``` - ### Custom cell actions ```swift import Tablet 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 61803cb7d4ddd5ef8ce9bdf7b59a32f84095fc17..7cb6250b7ac308caaadbbd147c4f7405e31e9db6 100644 GIT binary patch delta 10475 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 H<(&TqtJ@w1 From d0773704c4a26aadff80d54bd040f79677669a82 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 15 Nov 2015 16:43:01 +0300 Subject: [PATCH 23/25] readme updated --- README.md | 21 +++++++++++++----- .../UserInterfaceState.xcuserstate | Bin 26276 -> 26304 bytes 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e047841..72ea91a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ ![Tablet](https://raw.githubusercontent.com/maxsokolov/tablet/assets/tablet.png) +

+Platform iOS +Swift 2.1 compatible +License: MIT +

+ Tablet is a super lightweight yet powerful generic library that handles a complexity of UITableView's datasource and delegate methods in a Swift environment. Tablet's goal is to provide an easiest way to create complex table views. With Tablet you don't have to write a messy code of switch or if statements when you deal with bunch of different cells in different sections. That's almost all you need in your controller to build a bunch of cells in a section: @@ -50,7 +56,7 @@ let rowBuilder = TableRowBuilder(items: [user1, user2, us let sectionBuilder = TableSectionBuilder(headerTitle: "Users", rowBuilders: [rowBuilder]) -let director = TableDirector(tableView: tableView) +director = TableDirector(tableView: tableView) director.appendSections(sectionBuilder) ``` @@ -85,6 +91,7 @@ import Tablet let rowBuilder = TableConfigurableRowBuilder() rowBuilder.appendItems(users) +director = TableDirector(tableView: tableView) tableDirector.appendSection(TableSectionBuilder(rowBuilders: [rowBuilder])) ``` @@ -95,7 +102,7 @@ Tablet provides a chaining approach to handle actions from your cells: ```swift import Tablet -let rowBuilder = TableRowBuilder(items: [user1, user2, user3], id: "reusable_id") +let rowBuilder = TableRowBuilder(items: [user1, user2, user3], id: "reusable_id") .action(.configure) { data in } @@ -111,11 +118,13 @@ let rowBuilder = TableRowBuilder(items: [user1, user2, us ```swift import Tablet -class UserTableViewCell : UITableViewCell { +let kMyAction = "action_key" + +class MyTableViewCell : UITableViewCell { @IBAction func buttonClicked(sender: UIButton) { - Action(key: "action_key", sender: self, userInfo: nil).trigger() + Action(key: kMyAction, sender: self, userInfo: nil).trigger() } } ``` @@ -123,14 +132,14 @@ And receive this actions with your row builder: ```swift import Tablet -let rowBuilder = TableRowBuilder(items: users, id: "reusable_id") +let rowBuilder = TableConfigurableRowBuilder(items: users, id: "reusable_id", estimatedRowHeight: 42) .action(.click) { data in } .action(.willDisplay) { data in } - .action("action_key") { data in + .action(kMyAction) { data in } ``` 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 7cb6250b7ac308caaadbbd147c4f7405e31e9db6..066f0b0a4d703d999d3f99688b8d56aebb1f6a56 100644 GIT binary patch delta 5676 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 T+wlttf;vW6)-nFCFYEVz*0nHM delta 5497 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 From e25b7d759ec40886ea8679e08d85d4d930b4a1c3 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 15 Nov 2015 17:50:53 +0300 Subject: [PATCH 24/25] readme updated, some refactoring --- README.md | 53 +++++++++++++----- Tablet/TableDirector.swift | 25 ++++----- Tablet/TableRowBuilder.swift | 6 +- Tablet/Tablet.swift | 4 +- .../UserInterfaceState.xcuserstate | Bin 26304 -> 25546 bytes .../ConfigurableTableViewCell.swift | 2 +- .../TabletDemo/CustomTableActions.swift | 10 ++++ TabletDemo/TabletDemo/ViewController.swift | 4 ++ 8 files changed, 72 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 72ea91a..23d35e5 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ ![Tablet](https://raw.githubusercontent.com/maxsokolov/tablet/assets/tablet.png)

+Swift 2 compatible Platform iOS -Swift 2.1 compatible +CocoaPods compatible License: MIT

@@ -70,17 +71,17 @@ import Tablet class MyTableViewCell : UITableViewCell, ConfigurableCell { - typealias Item = User - - static func reusableIdentifier() -> String { - return "reusable_id" - } + typealias Item = User - func configureWithItem(item: Item) { // item is user here + static func reusableIdentifier() -> String { + return "reusable_id" + } - textLabel?.text = item.username + func configureWithItem(item: Item) { // item is user here + + textLabel?.text = item.username detailTextLabel?.text = item.isActive ? "Active" : "Inactive" - } + } } ``` Once you've implemented the protocol, simply use the `TableConfigurableRowBuilder` to build cells: @@ -107,10 +108,11 @@ let rowBuilder = TableRowBuilder(items: [user1, user2, us } .action(.click) { data in - + } - .action(.willDisplay) { data in - + .action(.shouldHighlight) { data in + + return false } ``` @@ -124,7 +126,7 @@ class MyTableViewCell : UITableViewCell { @IBAction func buttonClicked(sender: UIButton) { - Action(key: kMyAction, sender: self, userInfo: nil).trigger() + Action(key: kMyAction, sender: self, userInfo: nil).perform() } } ``` @@ -144,6 +146,31 @@ let rowBuilder = TableConfigurableRowBuilder(items: users } ``` +## Extensibility + +If you find that Tablet is not provide an action you need, for example you need UITableViewDelegate's `didEndDisplayingCell` method and it's not out of the box, +simply provide an extension for `TableDirector` as follow: +```swift +import Tablet + +let kTableDirectorDidEndDisplayingCell = "enddisplaycell" + +extension TableDirector { + + public func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { + + performAction(.custom(kTableDirectordidEndDisplayingCell), cell: cell, indexPath: indexPath) + } +} +``` +Catch your action with row builder: +```swift +let rowBuilder = TableConfigurableRowBuilder(items: users) + .action(kTableDirectordidEndDisplayingCell) { data in + + } +``` + ## License Tablet is available under the MIT license. See LICENSE for details. \ No newline at end of file diff --git a/Tablet/TableDirector.swift b/Tablet/TableDirector.swift index b8bb781..30c6daf 100644 --- a/Tablet/TableDirector.swift +++ b/Tablet/TableDirector.swift @@ -69,10 +69,10 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate return sections[indexPath.section].builderAtIndex(indexPath.row)! } - public func triggerAction(action: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath) -> AnyObject? { + public func performAction(action: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath) -> AnyObject? { let builder = builderAtIndexPath(indexPath) - return builder.0.triggerAction(action, cell: cell, indexPath: indexPath, itemIndex: builder.1) + return builder.0.performAction(action, cell: cell, indexPath: indexPath, itemIndex: builder.1) } internal func didReceiveAction(notification: NSNotification) { @@ -80,7 +80,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate if let action = notification.object as? Action, indexPath = tableView.indexPathForCell(action.cell) { let builder = builderAtIndexPath(indexPath) - builder.0.triggerAction(.custom(action.key), cell: action.cell, indexPath: indexPath, itemIndex: builder.1) + builder.0.performAction(.custom(action.key), cell: action.cell, indexPath: indexPath, itemIndex: builder.1) } } @@ -102,7 +102,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate let cell = tableView.dequeueReusableCellWithIdentifier(builder.0.reusableIdentifier, forIndexPath: indexPath) - builder.0.triggerAction(.configure, cell: cell, indexPath: indexPath, itemIndex: builder.1) + builder.0.performAction(.configure, cell: cell, indexPath: indexPath, itemIndex: builder.1) return cell } @@ -155,34 +155,33 @@ extension TableDirector { } public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { - - - return triggerAction(.height, cell: nil, indexPath: indexPath) as? CGFloat ?? UITableViewAutomaticDimension + + return performAction(.height, cell: nil, indexPath: indexPath) as? CGFloat ?? UITableViewAutomaticDimension } public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { let cell = tableView.cellForRowAtIndexPath(indexPath) - if triggerAction(.click, cell: cell, indexPath: indexPath) != nil { + if performAction(.click, cell: cell, indexPath: indexPath) != nil { tableView.deselectRowAtIndexPath(indexPath, animated: true) } else { - triggerAction(.select, cell: cell, indexPath: indexPath) + performAction(.select, cell: cell, indexPath: indexPath) } } public func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) { - triggerAction(.deselect, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) + performAction(.deselect, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) } public func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { - - triggerAction(.willDisplay, cell: cell, indexPath: indexPath) + + performAction(.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 + return performAction(.shouldHighlight, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? Bool ?? true } } \ No newline at end of file diff --git a/Tablet/TableRowBuilder.swift b/Tablet/TableRowBuilder.swift index a09de24..edd2854 100644 --- a/Tablet/TableRowBuilder.swift +++ b/Tablet/TableRowBuilder.swift @@ -107,7 +107,7 @@ public class TableRowBuilder : RowBuilder { // MARK: Triggers - public func triggerAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? { + public func performAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? { if let action = actions[actionType.key] { return action.call(ActionData(cell: cell as? C, indexPath: indexPath, item: items[itemIndex], itemIndex: itemIndex)) @@ -129,13 +129,13 @@ public class TableConfigurableRowBuilder AnyObject? { + public override func performAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? { switch actionType { case .configure: (cell as? C)?.configureWithItem(items[itemIndex]) default: break } - return super.triggerAction(actionType, cell: cell, indexPath: indexPath, itemIndex: itemIndex) + return super.performAction(actionType, cell: cell, indexPath: indexPath, itemIndex: itemIndex) } } diff --git a/Tablet/Tablet.swift b/Tablet/Tablet.swift index 6ceeeaf..3331c53 100644 --- a/Tablet/Tablet.swift +++ b/Tablet/Tablet.swift @@ -86,7 +86,7 @@ public class Action { self.userInfo = userInfo } - public func trigger() { + public func perform() { NSNotificationCenter.defaultCenter().postNotificationName(kActionPerformedNotificationKey, object: self) } @@ -114,5 +114,5 @@ public protocol RowBuilder { var reusableIdentifier: String { get } var estimatedRowHeight: CGFloat { get } - func triggerAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? + func performAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int) -> AnyObject? } \ No newline at end of file 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 066f0b0a4d703d999d3f99688b8d56aebb1f6a56..fe7b4a04a38e9e02e3850aadfc1a2659c7d4146f 100644 GIT binary patch delta 8578 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 JF&O2&{vY!I<}v^P diff --git a/TabletDemo/TabletDemo/ConfigurableTableViewCell.swift b/TabletDemo/TabletDemo/ConfigurableTableViewCell.swift index a83405f..07be0a2 100644 --- a/TabletDemo/TabletDemo/ConfigurableTableViewCell.swift +++ b/TabletDemo/TabletDemo/ConfigurableTableViewCell.swift @@ -29,6 +29,6 @@ class ConfigurableTableViewCell: UITableViewCell, ConfigurableCell { @IBAction func buttonClicked(sender: UIButton) { - Action(key: kConfigurableTableViewCellButtonClickedAction, sender: self).trigger() + Action(key: kConfigurableTableViewCellButtonClickedAction, sender: self).perform() } } \ No newline at end of file diff --git a/TabletDemo/TabletDemo/CustomTableActions.swift b/TabletDemo/TabletDemo/CustomTableActions.swift index 3c55cd9..c586a75 100644 --- a/TabletDemo/TabletDemo/CustomTableActions.swift +++ b/TabletDemo/TabletDemo/CustomTableActions.swift @@ -8,3 +8,13 @@ import UIKit import Foundation + +let kTableDirectorDidEndDisplayingCell = "enddisplaycell" + +extension TableDirector { + + public func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { + + performAction(.custom(kTableDirectorDidEndDisplayingCell), cell: cell, indexPath: indexPath) + } +} \ No newline at end of file diff --git a/TabletDemo/TabletDemo/ViewController.swift b/TabletDemo/TabletDemo/ViewController.swift index 3638950..240941c 100644 --- a/TabletDemo/TabletDemo/ViewController.swift +++ b/TabletDemo/TabletDemo/ViewController.swift @@ -27,6 +27,10 @@ class ViewController: UIViewController { return false } + .action(kTableDirectorDidEndDisplayingCell) { data -> Void in + + print("end display: \(data.indexPath)") + } let configurableRowBuilder = TableConfigurableRowBuilder(items: ["5", "6", "7", "8"], estimatedRowHeight: 300) .action(.click) { data -> Void in From a268a726bb74bc0f93baacf1a45e90391748954f Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Sun, 15 Nov 2015 19:29:30 +0300 Subject: [PATCH 25/25] readme updated --- README.md | 11 ++++++----- Tablet.podspec | 2 +- .../UserInterfaceState.xcuserstate | Bin 25546 -> 25548 bytes TabletDemo/TabletDemo/ViewController.swift | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 23d35e5..d23abe9 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ License: MIT

-Tablet is a super lightweight yet powerful generic library that handles a complexity of UITableView's datasource and delegate methods in a Swift environment. Tablet's goal is to provide an easiest way to create complex table views. With Tablet you don't have to write a messy code of switch or if statements when you deal with bunch of different cells in different sections. +Tablet is a super lightweight yet powerful generic library that handles a complexity of UITableView's datasource and delegate methods in a Swift environment. Tablet's goal is to provide an easiest way to create complex table views. With Tablet you don't have to write a messy code of `switch` or `if` statements when you deal with bunch of different cells in different sections. That's almost all you need in your controller to build a bunch of cells in a section: ```swift @@ -89,7 +89,7 @@ Once you've implemented the protocol, simply use the `TableConfigurableRowBuilde ```swift import Tablet -let rowBuilder = TableConfigurableRowBuilder() +let rowBuilder = TableConfigurableRowBuilder(estimatedRowHeight: 42) rowBuilder.appendItems(users) director = TableDirector(tableView: tableView) @@ -159,17 +159,18 @@ extension TableDirector { public func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { - performAction(.custom(kTableDirectordidEndDisplayingCell), cell: cell, indexPath: indexPath) + performAction(.custom(kTableDirectorDidEndDisplayingCell), cell: cell, indexPath: indexPath) } } ``` Catch your action with row builder: ```swift -let rowBuilder = TableConfigurableRowBuilder(items: users) - .action(kTableDirectordidEndDisplayingCell) { data in +let rowBuilder = TableConfigurableRowBuilder(items: users, estimatedRowHeight: 42) + .action(kTableDirectorDidEndDisplayingCell) { data in } ``` +You could also perform an action that returns a value. ## License diff --git a/Tablet.podspec b/Tablet.podspec index 5d4d01f..de7a9f9 100644 --- a/Tablet.podspec +++ b/Tablet.podspec @@ -3,7 +3,7 @@ Pod::Spec.new do |s| s.version = '0.1.0' s.homepage = 'https://github.com/maxsokolov/tablet' - s.summary = 'Tablet is a super lightweight yet powerful Swift library that handles a complexity of UITableView's datasource and delegate.' + s.summary = 'Powerful type-safe tool for UITableView. Swift 2.0 is required.' s.author = { 'Max Sokolov' => 'i@maxsokolov.net' } s.license = { :type => 'MIT', :file => 'LICENSE' } 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 fe7b4a04a38e9e02e3850aadfc1a2659c7d4146f..37a26d591729787b08719fcdb0e923493a543e62 100644 GIT binary patch delta 4484 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 delta 4567 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

kB&llxG`I3BD ferbL<|NZ Void in - data.cell!.contentLabel.text = "With iOS 8, Apple has internalized much of the work that previously had to be implemented by you prior to iOS 8. In order to allow the self-sizing cell mechanism to work, you must first set the rowHeight property on the table view to the constant UITableViewAutomaticDimension. Then, you simply need to enable row height estimation by setting the table view's estimatedRowHeight property to a nonzero value, for example" + data.cell!.contentLabel.text = "Tablet is a super lightweight yet powerful generic library that handles a complexity of UITableView's datasource and delegate methods in a Swift environment. Tablet's goal is to provide an easiest way to create complex table views. With Tablet you don't have to write a messy code of switch or if statements when you deal with bunch of different cells in different sections." } let sectionBuilder = TableSectionBuilder(headerTitle: "Tablet", footerTitle: "Deal with table view like a boss.", rowBuilders: [rowBuilder, configurableRowBuilder])