Merge pull request #40 from maxsokolov/develop

Significant performance improvements for prototypes
This commit is contained in:
Max Sokolov 2016-09-16 12:37:20 +04:00 committed by GitHub
commit c09e06f67d
13 changed files with 62 additions and 35 deletions

View File

@ -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: ())

View File

@ -34,7 +34,7 @@ class MainController: UIViewController {
break
}
}
let rows: [Row] = [
TableRow<String, ConfigurableTableViewCell>(item: "Autolayout cells", actions: [clickAction]),

View File

@ -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
}
}

View File

@ -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>

View File

@ -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>

View File

@ -42,7 +42,7 @@ public extension ConfigurableCell where Self: UITableViewCell {
static var estimatedHeight: CGFloat? {
get {
return UITableViewAutomaticDimension
return nil
}
}

View File

@ -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
}

View File

@ -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 {

View File

@ -20,8 +20,8 @@
import UIKit
class TableCellManager {
class TableCellRegisterer {
private var registeredIds = Set<String>()
private weak var tableView: UITableView?

View File

@ -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 {

View File

@ -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) {

View File

@ -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.'

View File

@ -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 */,