From d5ed53a0b6027ca4314943e579930d08396184b5 Mon Sep 17 00:00:00 2001 From: Ivan Smolin Date: Wed, 8 Jun 2016 18:12:57 +0300 Subject: [PATCH] table controller --- LeadKit/.gitignore => .gitignore | 0 LeadKit/Cartfile => Cartfile | 0 Cartfile.resolved | 1 + LeadKit/Cartfile.resolved | 1 - LeadKit/LeadKit.xcodeproj/project.pbxproj | 31 +++-- .../Controllers/TableViewController.swift | 119 ++++++++++++++++++ .../Protocols/CellsControllerProtocol.swift | 45 +++++++ 7 files changed, 189 insertions(+), 8 deletions(-) rename LeadKit/.gitignore => .gitignore (100%) rename LeadKit/Cartfile => Cartfile (100%) create mode 100644 Cartfile.resolved delete mode 100644 LeadKit/Cartfile.resolved create mode 100644 LeadKit/LeadKit/Controllers/TableViewController.swift create mode 100644 LeadKit/LeadKit/Protocols/CellsControllerProtocol.swift diff --git a/LeadKit/.gitignore b/.gitignore similarity index 100% rename from LeadKit/.gitignore rename to .gitignore diff --git a/LeadKit/Cartfile b/Cartfile similarity index 100% rename from LeadKit/Cartfile rename to Cartfile diff --git a/Cartfile.resolved b/Cartfile.resolved new file mode 100644 index 00000000..83cef058 --- /dev/null +++ b/Cartfile.resolved @@ -0,0 +1 @@ +github "CocoaLumberjack/CocoaLumberjack" "2.3.0" diff --git a/LeadKit/Cartfile.resolved b/LeadKit/Cartfile.resolved deleted file mode 100644 index bfc8d2e4..00000000 --- a/LeadKit/Cartfile.resolved +++ /dev/null @@ -1 +0,0 @@ -github "CocoaLumberjack/CocoaLumberjack" "2.2.0" diff --git a/LeadKit/LeadKit.xcodeproj/project.pbxproj b/LeadKit/LeadKit.xcodeproj/project.pbxproj index 996e9afc..fa8dfb3a 100644 --- a/LeadKit/LeadKit.xcodeproj/project.pbxproj +++ b/LeadKit/LeadKit.xcodeproj/project.pbxproj @@ -8,12 +8,14 @@ /* Begin PBXBuildFile section */ 7824CA521CFEE6B700D7B132 /* UIImage+RenderTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7824CA511CFEE6B700D7B132 /* UIImage+RenderTemplate.swift */; }; - 7830C4151C6B337D00180D02 /* CocoaLumberjack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7830C4141C6B337D00180D02 /* CocoaLumberjack.framework */; }; 7837F60F1CBCF5C0000D74C1 /* EstimatedViewHeightProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7837F60E1CBCF5C0000D74C1 /* EstimatedViewHeightProtocol.swift */; }; + 785C33451CFC908800C4C4AA /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 785C33441CFC908800C4C4AA /* TableViewController.swift */; }; 786A17A11CB8D71D007F9661 /* UIImage+CapInsetsUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 786A17A01CB8D71D007F9661 /* UIImage+CapInsetsUtils.swift */; }; 787682FA1CAD40C300532AB3 /* StaticEstimatedViewHeightProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787682F91CAD40C200532AB3 /* StaticEstimatedViewHeightProtocol.swift */; }; 787783631CA03CA0001CDC9B /* NSIndexPath+ImmutableIndexPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787783621CA03CA0001CDC9B /* NSIndexPath+ImmutableIndexPath.swift */; }; 787783671CA04D4A001CDC9B /* NSString+SizeCalculation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787783661CA04D4A001CDC9B /* NSString+SizeCalculation.swift */; }; + 787A071A1D085750009EC97F /* CellsControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787A07191D085750009EC97F /* CellsControllerProtocol.swift */; }; + 787A071E1D08790B009EC97F /* CocoaLumberjack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 787A071D1D08790B009EC97F /* CocoaLumberjack.framework */; }; 788EC15A1CF64528009CFB6B /* UIStoryboard+InstantiateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 788EC1591CF64528009CFB6B /* UIStoryboard+InstantiateViewController.swift */; }; 78A74EA91C6B373700FE9724 /* UIView+DefaultNibName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78A74EA81C6B373700FE9724 /* UIView+DefaultNibName.swift */; }; 78B0FC7D1C6B2BE200358B64 /* LogFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78B0FC7C1C6B2BE200358B64 /* LogFormatter.swift */; }; @@ -48,12 +50,14 @@ /* Begin PBXFileReference section */ 7824CA511CFEE6B700D7B132 /* UIImage+RenderTemplate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+RenderTemplate.swift"; sourceTree = ""; }; - 7830C4141C6B337D00180D02 /* CocoaLumberjack.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CocoaLumberjack.framework; path = Carthage/Build/iOS/CocoaLumberjack.framework; sourceTree = SOURCE_ROOT; }; 7837F60E1CBCF5C0000D74C1 /* EstimatedViewHeightProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimatedViewHeightProtocol.swift; sourceTree = ""; }; + 785C33441CFC908800C4C4AA /* TableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = ""; }; 786A17A01CB8D71D007F9661 /* UIImage+CapInsetsUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+CapInsetsUtils.swift"; sourceTree = ""; }; 787682F91CAD40C200532AB3 /* StaticEstimatedViewHeightProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StaticEstimatedViewHeightProtocol.swift; sourceTree = ""; }; 787783621CA03CA0001CDC9B /* NSIndexPath+ImmutableIndexPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSIndexPath+ImmutableIndexPath.swift"; sourceTree = ""; }; 787783661CA04D4A001CDC9B /* NSString+SizeCalculation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSString+SizeCalculation.swift"; sourceTree = ""; }; + 787A07191D085750009EC97F /* CellsControllerProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellsControllerProtocol.swift; sourceTree = ""; }; + 787A071D1D08790B009EC97F /* CocoaLumberjack.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CocoaLumberjack.framework; path = ../../../Carthage/Build/iOS/CocoaLumberjack.framework; sourceTree = ""; }; 788EC1591CF64528009CFB6B /* UIStoryboard+InstantiateViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIStoryboard+InstantiateViewController.swift"; sourceTree = ""; }; 78A74EA81C6B373700FE9724 /* UIView+DefaultNibName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UIView+DefaultNibName.swift"; path = "LeadKit/Extensions/UIView/UIView+DefaultNibName.swift"; sourceTree = SOURCE_ROOT; }; 78B0FC7C1C6B2BE200358B64 /* LogFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogFormatter.swift; sourceTree = ""; }; @@ -84,7 +88,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 7830C4151C6B337D00180D02 /* CocoaLumberjack.framework in Frameworks */, + 787A071E1D08790B009EC97F /* CocoaLumberjack.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -102,11 +106,20 @@ 7830C4131C6B336A00180D02 /* Frameworks */ = { isa = PBXGroup; children = ( - 7830C4141C6B337D00180D02 /* CocoaLumberjack.framework */, + 787A071D1D08790B009EC97F /* CocoaLumberjack.framework */, ); path = Frameworks; sourceTree = ""; }; + 785C33431CFC89EF00C4C4AA /* Controllers */ = { + isa = PBXGroup; + children = ( + 785C33441CFC908800C4C4AA /* TableViewController.swift */, + ); + name = Controllers; + path = ../Controllers; + sourceTree = ""; + }; 787783611CA03C84001CDC9B /* NSIndexPath */ = { isa = PBXGroup; children = ( @@ -126,6 +139,7 @@ 78A74EAA1C6B401800FE9724 /* Classes */ = { isa = PBXGroup; children = ( + 785C33431CFC89EF00C4C4AA /* Controllers */, 78E59B171C773E9600C6BFE9 /* Cache */, 78B0FC7B1C6B2BAE00358B64 /* Logging */, ); @@ -207,6 +221,7 @@ 78CFEE501C5C45E500F50370 /* ViewModelProtocol.swift */, 787682F91CAD40C200532AB3 /* StaticEstimatedViewHeightProtocol.swift */, 7837F60E1CBCF5C0000D74C1 /* EstimatedViewHeightProtocol.swift */, + 787A07191D085750009EC97F /* CellsControllerProtocol.swift */, ); path = Protocols; sourceTree = ""; @@ -396,7 +411,7 @@ files = ( ); inputPaths = ( - "$(SRCROOT)/Carthage/Build/iOS/CocoaLumberjack.framework", + "$(SRCROOT)/../Carthage/Build/iOS/CocoaLumberjack.framework", ); name = "Carthage copy-frameworks"; outputPaths = ( @@ -412,6 +427,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 785C33451CFC908800C4C4AA /* TableViewController.swift in Sources */, 7837F60F1CBCF5C0000D74C1 /* EstimatedViewHeightProtocol.swift in Sources */, 78CFEE541C5C45E500F50370 /* UIView+LoadFromNib.swift in Sources */, 78CFEE521C5C45E500F50370 /* UITableView+CellRegistration.swift in Sources */, @@ -422,6 +438,7 @@ 78CFEE531C5C45E500F50370 /* UITableView+DequeueCustomCell.swift in Sources */, 78E59B1B1C77470A00C6BFE9 /* ViewsGenerator.swift in Sources */, 78B0FC811C6B2CD500358B64 /* App.swift in Sources */, + 787A071A1D085750009EC97F /* CellsControllerProtocol.swift in Sources */, 78CFEE551C5C45E500F50370 /* NibNameProtocol.swift in Sources */, 78CFEE561C5C45E500F50370 /* ReuseIdentifierProtocol.swift in Sources */, 78E59B191C773EE600C6BFE9 /* ObjectsGenerator.swift in Sources */, @@ -557,7 +574,7 @@ "$(inherited)", "$(PROJECT_DIR)/LeadKit", "$(PROJECT_DIR)/LeadKit/Frameworks", - "$(PROJECT_DIR)/Carthage/Build/iOS", + "$(PROJECT_DIR)/../Carthage/Build/iOS", ); INFOPLIST_FILE = LeadKit/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -580,7 +597,7 @@ "$(inherited)", "$(PROJECT_DIR)/LeadKit", "$(PROJECT_DIR)/LeadKit/Frameworks", - "$(PROJECT_DIR)/Carthage/Build/iOS", + "$(PROJECT_DIR)/../Carthage/Build/iOS", ); INFOPLIST_FILE = LeadKit/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; diff --git a/LeadKit/LeadKit/Controllers/TableViewController.swift b/LeadKit/LeadKit/Controllers/TableViewController.swift new file mode 100644 index 00000000..4abee065 --- /dev/null +++ b/LeadKit/LeadKit/Controllers/TableViewController.swift @@ -0,0 +1,119 @@ +// +// TableViewController.swift +// LeadKit +// +// Created by Ivan Smolin on 30/05/16. +// Copyright © 2016 Touch Instinct. All rights reserved. +// + +import UIKit + +public enum CellCreationType: Int { + + case Preloaded = 0 + case OnTheFlight = 1 + +} + +public class TableViewController: UITableViewController, CellsControllerProtocol { + + private var heightCache: [NSIndexPath: CGFloat] = [:] + + private var cellsObjectsCreators: [String: ViewsGenerator] = [:] + + private let cellCreationType: CellCreationType + + // MARK: - Initialization + + public init(style: UITableViewStyle, cellCreationType: CellCreationType = .OnTheFlight) { + self.cellCreationType = cellCreationType + super.init(style: style) + } + + public required init?(coder aDecoder: NSCoder) { + if let cellCreationType = CellCreationType(rawValue: aDecoder.decodeIntegerForKey("CellCreationType")) { + self.cellCreationType = cellCreationType + super.init(coder: aDecoder) + } else { + return nil + } + } + + public override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + + invalidateCache() + } + + public override func encodeWithCoder(aCoder: NSCoder) { + super.encodeWithCoder(aCoder) + aCoder.encodeInteger(cellCreationType.rawValue, forKey: "CellCreationType") + } + + public func registerCellsGenerator(cellsGenerator: ViewsGenerator, + forCellsWithIdentifier cellIdentifier: String) { + cellsObjectsCreators[cellIdentifier] = cellsGenerator + } + + // MARK: - Table view data source + + public override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + let cell: UITableViewCell + + let cellIdentifier = cellIdentifierForIndexPath(indexPath) + + switch cellCreationType { + case .OnTheFlight: + cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) + case .Preloaded: + guard let cellsGenerator = cellsObjectsCreators[cellIdentifier] else { + fatalError("You should register view generator for cell with identifier \"\(cellIdentifier)\"") + } + + cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) ?? cellsGenerator.get() + } + + configureCell(cell, atIndexPath: indexPath) + + return cell + } + + // MARK: - Table view delegate + + public override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { + let immutableIndex = indexPath.immutableIndexPath + + let cellHeight: CGFloat + + if let cachedheight = heightCache[immutableIndex] { + cellHeight = cachedheight + } else { + cellHeight = heightForCellAtIndexPath(immutableIndex) + heightCache[immutableIndex] = cellHeight + } + + return cellHeight + } + + // MARK: - Cache + + public func invalidateCache() { + heightCache = [:] + } + + // MARK: - Cells сontroller stub implementation + + public func cellIdentifierForIndexPath(indexPath: NSIndexPath) -> String { + fatalError("Your should implement cellIdentifierForIndexPath(_:)") + } + + public func configureCell(cell: UITableViewCell, atIndexPath: NSIndexPath) { + // intended to be implemented in subclasses + } + + public func heightForCellAtIndexPath(indexPath: NSIndexPath) -> CGFloat { + // intended to be implemented in subclasses + return UITableViewAutomaticDimension + } + +} diff --git a/LeadKit/LeadKit/Protocols/CellsControllerProtocol.swift b/LeadKit/LeadKit/Protocols/CellsControllerProtocol.swift new file mode 100644 index 00000000..09845277 --- /dev/null +++ b/LeadKit/LeadKit/Protocols/CellsControllerProtocol.swift @@ -0,0 +1,45 @@ +// +// CellsControllerProtocol.swift +// LeadKit +// +// Created by Ivan Smolin on 08/06/16. +// Copyright © 2016 Touch Instinct. All rights reserved. +// + +import Foundation + +/** + * protocol which ensures that specific type can configure cell and return cell attributes for specific index path + */ +public protocol CellsControllerProtocol { + associatedtype CellType + + /** + method which returns cell identifier for given index path + + - parameter indexPath: NSIndexPath object + + - returns: cell identifier for specified index path + */ + func cellIdentifierForIndexPath(indexPath: NSIndexPath) -> String + + /** + method which configures given cell for given index path + + - parameter cell: cell to configure + - parameter atIndexPath: index path of given cell + + - returns: nothing + */ + func configureCell(cell: CellType, atIndexPath: NSIndexPath) + + /** + method which returns height of cell for given index path + + - parameter indexPath: NSIndexPath object + + - returns: height of cell for specified index path + */ + func heightForCellAtIndexPath(indexPath: NSIndexPath) -> CGFloat + +}