Merge pull request #40 from maxsokolov/develop
Significant performance improvements for prototypes
This commit is contained in:
commit
c09e06f67d
|
|
@ -14,6 +14,7 @@ class AutolayoutCellsController: UIViewController {
|
|||
@IBOutlet weak var tableView: UITableView! {
|
||||
didSet {
|
||||
tableDirector = TableDirector(tableView: tableView)
|
||||
tableDirector.shouldUsePrototypeCellHeightCalculation = true
|
||||
}
|
||||
}
|
||||
var tableDirector: TableDirector!
|
||||
|
|
@ -26,7 +27,7 @@ class AutolayoutCellsController: UIViewController {
|
|||
let section = TableSection()
|
||||
|
||||
var rows = 0
|
||||
while rows <= 10 {
|
||||
while rows <= 1000 {
|
||||
rows += 1
|
||||
|
||||
let row = TableRow<Void, AutolayoutTableViewCell>(item: ())
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class MainController: UIViewController {
|
|||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let rows: [Row] = [
|
||||
|
||||
TableRow<String, ConfigurableTableViewCell>(item: "Autolayout cells", actions: [clickAction]),
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ class AutolayoutTableViewCell: UITableViewCell, ConfigurableCell {
|
|||
|
||||
@IBOutlet var titleLabel: UILabel!
|
||||
@IBOutlet var subtitleLabel: UILabel!
|
||||
|
||||
|
||||
static var estimatedHeight: CGFloat? {
|
||||
return 500
|
||||
return 700
|
||||
}
|
||||
|
||||
func configure(with string: T) {
|
||||
|
|
@ -28,4 +28,13 @@ class AutolayoutTableViewCell: UITableViewCell, ConfigurableCell {
|
|||
titleLabel.text = LoremIpsumTitle
|
||||
subtitleLabel.text = LoremIpsumBody
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
contentView.layoutIfNeeded()
|
||||
|
||||
titleLabel.preferredMaxLayoutWidth = titleLabel.bounds.size.width
|
||||
subtitleLabel.preferredMaxLayoutWidth = subtitleLabel.bounds.size.width
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10116" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
|
|
@ -11,19 +11,21 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="4JI-V9-Bra" id="Bal-V1-EZ2">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qBe-iP-Q1p">
|
||||
<rect key="frame" x="8" y="11" width="45" height="21"/>
|
||||
<rect key="frame" x="8" y="11" width="304" height="21"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="qBe-iP-Q1p" firstAttribute="centerY" secondItem="Bal-V1-EZ2" secondAttribute="centerY" id="8gn-1I-szV"/>
|
||||
<constraint firstItem="qBe-iP-Q1p" firstAttribute="leading" secondItem="Bal-V1-EZ2" secondAttribute="leading" constant="8" id="xMK-TB-Bis"/>
|
||||
<constraint firstItem="qBe-iP-Q1p" firstAttribute="top" secondItem="Bal-V1-EZ2" secondAttribute="top" constant="11" id="B84-GR-YoJ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="qBe-iP-Q1p" secondAttribute="bottom" constant="12" id="Cmh-Tj-2Pw"/>
|
||||
<constraint firstAttribute="trailing" secondItem="qBe-iP-Q1p" secondAttribute="trailing" constant="8" id="ZJP-9s-4ZM"/>
|
||||
<constraint firstItem="qBe-iP-Q1p" firstAttribute="leading" secondItem="Bal-V1-EZ2" secondAttribute="leading" constant="8" id="wAW-KV-dCJ"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<a href="https://travis-ci.org/maxsokolov/TableKit"><img src="https://api.travis-ci.org/maxsokolov/TableKit.svg" alt="Build Status" /></a>
|
||||
<a href="https://developer.apple.com/swift"><img src="https://img.shields.io/badge/Swift_2.2-compatible-4BC51D.svg?style=flat" alt="Swift 2.2 compatible" /></a>
|
||||
<a href="https://github.com/Carthage/Carthage"><img src="https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat" alt="Carthage compatible" /></a>
|
||||
<a href="https://cocoapods.org/pods/tablekit"><img src="https://img.shields.io/badge/pod-1.1.2-blue.svg" alt="CocoaPods compatible" /></a>
|
||||
<a href="https://cocoapods.org/pods/tablekit"><img src="https://img.shields.io/badge/pod-1.2.0-blue.svg" alt="CocoaPods compatible" /></a>
|
||||
<img src="https://img.shields.io/badge/platform-iOS-blue.svg?style=flat" alt="Platform iOS" />
|
||||
<a href="https://raw.githubusercontent.com/maxsokolov/tablekit/master/LICENSE"><img src="http://img.shields.io/badge/license-MIT-blue.svg?style=flat" alt="License: MIT" /></a>
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public extension ConfigurableCell where Self: UITableViewCell {
|
|||
|
||||
static var estimatedHeight: CGFloat? {
|
||||
get {
|
||||
return UITableViewAutomaticDimension
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,12 +49,18 @@ public class PrototypeHeightStrategy: CellHeightCalculatable {
|
|||
return height
|
||||
}
|
||||
|
||||
guard let cell = tableView.dequeueReusableCellWithIdentifier(row.reuseIdentifier) else { return 0 }
|
||||
var prototypeCell = prototypes[row.reuseIdentifier]
|
||||
if prototypeCell == nil {
|
||||
|
||||
cell.bounds = CGRectMake(0, 0, tableView.bounds.size.width, cell.bounds.height)
|
||||
prototypeCell = tableView.dequeueReusableCellWithIdentifier(row.reuseIdentifier)
|
||||
prototypes[row.reuseIdentifier] = prototypeCell
|
||||
}
|
||||
|
||||
guard let cell = prototypeCell else { return 0 }
|
||||
|
||||
row.configure(cell)
|
||||
|
||||
|
||||
cell.bounds = CGRectMake(0, 0, tableView.bounds.size.width, cell.bounds.height)
|
||||
cell.setNeedsLayout()
|
||||
cell.layoutIfNeeded()
|
||||
|
||||
|
|
@ -66,6 +72,19 @@ public class PrototypeHeightStrategy: CellHeightCalculatable {
|
|||
}
|
||||
|
||||
public func estimatedHeight(row: Row, path: NSIndexPath) -> CGFloat {
|
||||
|
||||
guard let tableView = tableView else { return 0 }
|
||||
|
||||
let hash = row.hashValue ^ Int(tableView.bounds.size.width).hashValue
|
||||
|
||||
if let height = cachedHeights[hash] {
|
||||
return height
|
||||
}
|
||||
|
||||
if let estimatedHeight = row.estimatedHeight where estimatedHeight > 0 {
|
||||
return estimatedHeight
|
||||
}
|
||||
|
||||
return UITableViewAutomaticDimension
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ struct TableKitNotifications {
|
|||
|
||||
/**
|
||||
A custom action that you can trigger from your cell.
|
||||
You can eacily catch actions using a chaining manner with your row builder.
|
||||
You can easily catch actions using a chaining manner with your row.
|
||||
*/
|
||||
public class TableCellAction {
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
class TableCellManager {
|
||||
|
||||
class TableCellRegisterer {
|
||||
|
||||
private var registeredIds = Set<String>()
|
||||
private weak var tableView: UITableView?
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
|
||||
private weak var scrollDelegate: UIScrollViewDelegate?
|
||||
private var heightStrategy: CellHeightCalculatable?
|
||||
private var cellManager: TableCellManager?
|
||||
private var cellRegisterer: TableCellRegisterer?
|
||||
|
||||
public var shouldUsePrototypeCellHeightCalculation: Bool = false {
|
||||
didSet {
|
||||
|
|
@ -48,7 +48,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
super.init()
|
||||
|
||||
if shouldUseAutomaticCellRegistration {
|
||||
self.cellManager = TableCellManager(tableView: tableView)
|
||||
self.cellRegisterer = TableCellRegisterer(tableView: tableView)
|
||||
}
|
||||
|
||||
self.scrollDelegate = scrollDelegate
|
||||
|
|
@ -98,14 +98,18 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
public func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
|
||||
|
||||
let row = sections[indexPath.section].rows[indexPath.row]
|
||||
|
||||
cellRegisterer?.register(cellType: row.cellType, forCellReuseIdentifier: row.reuseIdentifier)
|
||||
|
||||
return row.estimatedHeight ?? heightStrategy?.estimatedHeight(row, path: indexPath) ?? UITableViewAutomaticDimension
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
|
||||
|
||||
let row = sections[indexPath.section].rows[indexPath.row]
|
||||
|
||||
let rowHeight = invoke(action: .height, cell: nil, indexPath: indexPath) as? CGFloat
|
||||
|
||||
|
||||
return rowHeight ?? row.defaultHeight ?? heightStrategy?.height(row, path: indexPath) ?? UITableViewAutomaticDimension
|
||||
}
|
||||
|
||||
|
|
@ -122,9 +126,6 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
|
||||
|
||||
let row = sections[indexPath.section].rows[indexPath.row]
|
||||
|
||||
cellManager?.register(cellType: row.cellType, forCellReuseIdentifier: row.reuseIdentifier)
|
||||
|
||||
let cell = tableView.dequeueReusableCellWithIdentifier(row.reuseIdentifier, forIndexPath: indexPath)
|
||||
|
||||
if cell.frame.size.width != tableView.frame.size.width {
|
||||
|
|
|
|||
|
|
@ -84,13 +84,8 @@ public class TableSection {
|
|||
self.rows.insertContentsOf(rows, at: index)
|
||||
}
|
||||
|
||||
public func replace(rowAt index: Int, with row: Row) -> Bool {
|
||||
|
||||
if index >= 0 && index < rows.count {
|
||||
rows[index] = row
|
||||
return true
|
||||
}
|
||||
return false
|
||||
public func replace(rowAt index: Int, with row: Row) {
|
||||
rows[index] = row
|
||||
}
|
||||
|
||||
public func delete(index index: Int) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ Pod::Spec.new do |s|
|
|||
s.name = 'TableKit'
|
||||
s.module_name = 'TableKit'
|
||||
|
||||
s.version = '1.1.2'
|
||||
s.version = '1.2.0'
|
||||
|
||||
s.homepage = 'https://github.com/maxsokolov/TableKit'
|
||||
s.summary = 'Type-safe declarative table views. Swift 2.2 is required.'
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
50CF6E6B1D6704FE004746FF /* TableCellManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CF6E6A1D6704FE004746FF /* TableCellManager.swift */; };
|
||||
50CF6E6B1D6704FE004746FF /* TableCellRegisterer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CF6E6A1D6704FE004746FF /* TableCellRegisterer.swift */; };
|
||||
DA9EA7AF1D0EC2C90021F650 /* ConfigurableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7A61D0EC2C90021F650 /* ConfigurableCell.swift */; };
|
||||
DA9EA7B01D0EC2C90021F650 /* HeightStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7A71D0EC2C90021F650 /* HeightStrategy.swift */; };
|
||||
DA9EA7B11D0EC2C90021F650 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7A81D0EC2C90021F650 /* Operators.swift */; };
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
50CF6E6A1D6704FE004746FF /* TableCellManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableCellManager.swift; sourceTree = "<group>"; };
|
||||
50CF6E6A1D6704FE004746FF /* TableCellRegisterer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableCellRegisterer.swift; sourceTree = "<group>"; };
|
||||
DA9EA7561D0B679A0021F650 /* TableKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TableKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA9EA7A61D0EC2C90021F650 /* ConfigurableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurableCell.swift; sourceTree = "<group>"; };
|
||||
DA9EA7A71D0EC2C90021F650 /* HeightStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeightStrategy.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
DA9EA7AA1D0EC2C90021F650 /* TableDirector.swift */,
|
||||
50CF6E6A1D6704FE004746FF /* TableCellManager.swift */,
|
||||
50CF6E6A1D6704FE004746FF /* TableCellRegisterer.swift */,
|
||||
DA9EA7AB1D0EC2C90021F650 /* TableRow.swift */,
|
||||
DA9EA7AC1D0EC2C90021F650 /* TableRowAction.swift */,
|
||||
DA9EA7AE1D0EC2C90021F650 /* TableSection.swift */,
|
||||
|
|
@ -225,7 +225,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
50CF6E6B1D6704FE004746FF /* TableCellManager.swift in Sources */,
|
||||
50CF6E6B1D6704FE004746FF /* TableCellRegisterer.swift in Sources */,
|
||||
DA9EA7AF1D0EC2C90021F650 /* ConfigurableCell.swift in Sources */,
|
||||
DA9EA7B31D0EC2C90021F650 /* TableDirector.swift in Sources */,
|
||||
DA9EA7B71D0EC2C90021F650 /* TableSection.swift in Sources */,
|
||||
|
|
|
|||
Loading…
Reference in New Issue