code improvements, add examples

This commit is contained in:
Max Sokolov 2016-04-17 00:27:59 +03:00
parent 7d9d6ff60b
commit ef384cb0f1
9 changed files with 224 additions and 98 deletions

View File

@ -26,14 +26,14 @@ import Foundation
*/
public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate {
public private(set) weak var tableView: UITableView!
public unowned let tableView: UITableView
public weak var scrollDelegate: UIScrollViewDelegate?
private var sections = [TableSectionBuilder]()
public init(tableView: UITableView) {
super.init()
self.tableView = tableView
super.init()
self.tableView.delegate = self
self.tableView.dataSource = self
@ -41,7 +41,6 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}

View File

@ -29,10 +29,10 @@ public class TableSectionBuilder {
weak var tableView: UITableView?
private var builders = [RowBuilder]()
public var headerTitle: String?
public var footerTitle: String?
public var headerView: UIView?
public var footerView: UIView?
@ -41,18 +41,23 @@ public class TableSectionBuilder {
return builders.reduce(0) { $0 + $1.numberOfRows }
}
public init(headerTitle: String? = nil, footerTitle: String? = nil, rows: [RowBuilder]? = nil) {
self.headerTitle = headerTitle
self.footerTitle = footerTitle
public init(rows: [RowBuilder]? = nil) {
if let initialRows = rows {
builders.appendContentsOf(initialRows)
}
}
public init(headerView: UIView? = nil, footerView: UIView? = nil) {
public convenience init(headerTitle: String?, footerTitle: String?, rows: [RowBuilder]?) {
self.init(rows: rows)
self.headerTitle = headerTitle
self.footerTitle = footerTitle
}
public convenience init(headerView: UIView?, footerView: UIView?, rows: [RowBuilder]?) {
self.init(rows: rows)
self.headerView = headerView
self.footerView = footerView
}

View File

@ -0,0 +1,33 @@
//
// HeaderFooterController.swift
// TabletDemo
//
// Created by Max Sokolov on 16/04/16.
// Copyright © 2016 Tablet. All rights reserved.
//
import UIKit
import Tablet
class HeaderFooterController: UIViewController {
@IBOutlet weak var tableView: UITableView! {
didSet {
tableDirector = TableDirector(tableView: tableView)
}
}
var tableDirector: TableDirector!
override func viewDidLoad() {
super.viewDidLoad()
let rows = TableConfigurableRowBuilder<String, StoryboardTableViewCell>(items: ["3", "4", "5"])
let headerView = UIView(frame: CGRectMake(0, 0, 100, 100))
headerView.backgroundColor = UIColor.lightGrayColor()
let section = TableSectionBuilder(headerView: headerView, footerView: nil, rows: [rows])
tableDirector += section
}
}

View File

@ -0,0 +1,31 @@
//
// MainController.swift
// TabletDemo
//
// Created by Max Sokolov on 16/04/16.
// Copyright © 2016 Tablet. All rights reserved.
//
import UIKit
import Tablet
class MainController: UIViewController {
@IBOutlet weak var tableView: UITableView! {
didSet {
tableDirector = TableDirector(tableView: tableView)
}
}
var tableDirector: TableDirector!
override func viewDidLoad() {
super.viewDidLoad()
let rows = TableConfigurableRowBuilder<String, StoryboardTableViewCell>(items: ["1", "2", "3"])
.action(.click) { [unowned self] data -> Void in
self.performSegueWithIdentifier("headerfooter", sender: nil)
}
tableDirector += rows
}
}

View File

@ -1,33 +0,0 @@
//
// MainViewController.swift
// TabletDemo
//
// Created by Max Sokolov on 19/03/16.
// Copyright © 2016 Tablet. All rights reserved.
//
import Foundation
import UIKit
import Tablet
class MainViewController : UITableViewController {
var tableDirector: TableDirector!
override func viewDidLoad() {
super.viewDidLoad()
tableDirector = TableDirector(tableView: tableView)
tableDirector += TableRowBuilder<Int, UITableViewCell>(items: [1, 2, 3, 4], id: "cell")
.action(.configure) { data -> Void in
data.cell?.accessoryType = .DisclosureIndicator
data.cell?.textLabel?.text = "\(data.item)"
}
.action(.click) { data -> Void in
}
}
}

View File

@ -0,0 +1,23 @@
//
// StoryboardTableViewCell.swift
// TabletDemo
//
// Created by Max Sokolov on 16/04/16.
// Copyright © 2016 Tablet. All rights reserved.
//
import UIKit
import Tablet
class StoryboardTableViewCell: UITableViewCell, ConfigurableCell {
typealias T = String
func configure(value: T) {
textLabel?.text = value
}
static func estimatedHeight() -> Float {
return 44
}
}

View File

@ -1,39 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="dOU-ON-YYD">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="dOU-ON-YYD">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Main View Controller-->
<scene sceneID="oP2-EZ-N5W">
<objects>
<tableViewController id="ZyD-Ww-nfe" customClass="MainViewController" customModule="TabletDemo" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="xii-6e-J4f">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="cell" id="eQJ-7O-k03">
<rect key="frame" x="0.0" y="92" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="eQJ-7O-k03" id="Ufi-z4-pLt">
<rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="ZyD-Ww-nfe" id="dup-HU-FfF"/>
<outlet property="delegate" destination="ZyD-Ww-nfe" id="bRX-uu-KTX"/>
</connections>
</tableView>
<navigationItem key="navigationItem" id="6ba-xC-prc"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="uxV-eY-exN" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1074" y="287"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="Nb3-Yi-ik8">
<objects>
@ -45,12 +16,101 @@
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="ZyD-Ww-nfe" kind="relationship" relationship="rootViewController" id="vRk-x4-ylh"/>
<segue destination="grv-aL-Qbb" kind="relationship" relationship="rootViewController" id="0SZ-hs-iUi"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="1px-T5-UXL" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="334" y="287"/>
</scene>
<!--Main Controller-->
<scene sceneID="bgC-Xq-OSw">
<objects>
<viewController id="grv-aL-Qbb" customClass="MainController" customModule="TabletDemo" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="COn-EH-LKP"/>
<viewControllerLayoutGuide type="bottom" id="iga-ib-rj1"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="5uw-uC-8lc">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="o67-xJ-fPW">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="StoryboardTableViewCell" id="nE5-Y5-OFf" customClass="StoryboardTableViewCell" customModule="TabletDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="92" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="nE5-Y5-OFf" id="3yF-sl-yNq">
<rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
</tableView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="iga-ib-rj1" firstAttribute="top" secondItem="o67-xJ-fPW" secondAttribute="bottom" id="jrJ-xl-S4k"/>
<constraint firstItem="o67-xJ-fPW" firstAttribute="top" secondItem="5uw-uC-8lc" secondAttribute="top" id="ntC-Lp-77v"/>
<constraint firstAttribute="trailing" secondItem="o67-xJ-fPW" secondAttribute="trailing" id="s2g-E1-S4V"/>
<constraint firstItem="o67-xJ-fPW" firstAttribute="leading" secondItem="5uw-uC-8lc" secondAttribute="leading" id="uWa-n0-GSQ"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="HPV-jJ-NPc"/>
<connections>
<outlet property="tableView" destination="o67-xJ-fPW" id="A8B-MV-tNa"/>
<segue destination="sSs-TX-Ch0" kind="show" identifier="headerfooter" id="Nbk-od-yC5"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="xij-Hw-J33" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1042" y="287"/>
</scene>
<!--Header Footer Controller-->
<scene sceneID="Jd0-of-RF9">
<objects>
<viewController id="sSs-TX-Ch0" customClass="HeaderFooterController" customModule="TabletDemo" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="s9s-Gu-3M6"/>
<viewControllerLayoutGuide type="bottom" id="Tux-up-dnH"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="CB5-10-J2D">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="uLr-Ff-utK">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="StoryboardTableViewCell" id="lqW-2N-6mf" customClass="StoryboardTableViewCell" customModule="TabletDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="92" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="lqW-2N-6mf" id="tjN-ow-437">
<rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
</tableView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="Tux-up-dnH" firstAttribute="top" secondItem="uLr-Ff-utK" secondAttribute="bottom" id="0jr-6S-PFB"/>
<constraint firstItem="uLr-Ff-utK" firstAttribute="top" secondItem="CB5-10-J2D" secondAttribute="top" id="KYu-01-hlH"/>
<constraint firstAttribute="trailing" secondItem="uLr-Ff-utK" secondAttribute="trailing" id="TKR-R1-lBY"/>
<constraint firstItem="uLr-Ff-utK" firstAttribute="leading" secondItem="CB5-10-J2D" secondAttribute="leading" id="aG6-R3-QUr"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="ogA-Id-clb"/>
<connections>
<outlet property="tableView" destination="uLr-Ff-utK" id="olP-LV-VmT"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Gim-O8-I3d" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1763" y="287"/>
</scene>
</scenes>
</document>

View File

@ -10,8 +10,10 @@
DAC2D5CA1C9D303E009E9C19 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC2D5C91C9D303E009E9C19 /* AppDelegate.swift */; };
DAC2D5CF1C9D30A7009E9C19 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DAC2D5CD1C9D30A7009E9C19 /* Main.storyboard */; };
DAC2D5D01C9D30A7009E9C19 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DAC2D5CE1C9D30A7009E9C19 /* LaunchScreen.storyboard */; };
DAC2D5D41C9D3118009E9C19 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC2D5D31C9D3118009E9C19 /* MainViewController.swift */; };
DAC2D69C1C9E75E3009E9C19 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DAC2D69B1C9E75E3009E9C19 /* Assets.xcassets */; };
DACB71761CC2D63D00432BD3 /* MainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DACB71751CC2D63D00432BD3 /* MainController.swift */; };
DACB71781CC2D6ED00432BD3 /* StoryboardTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DACB71771CC2D6ED00432BD3 /* StoryboardTableViewCell.swift */; };
DACB717A1CC2D89D00432BD3 /* HeaderFooterController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DACB71791CC2D89D00432BD3 /* HeaderFooterController.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@ -19,9 +21,11 @@
DAC2D5C91C9D303E009E9C19 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
DAC2D5CD1C9D30A7009E9C19 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
DAC2D5CE1C9D30A7009E9C19 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
DAC2D5D31C9D3118009E9C19 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; };
DAC2D69B1C9E75E3009E9C19 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
DAC2D69D1C9E78B5009E9C19 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
DACB71751CC2D63D00432BD3 /* MainController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainController.swift; sourceTree = "<group>"; };
DACB71771CC2D6ED00432BD3 /* StoryboardTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoryboardTableViewCell.swift; sourceTree = "<group>"; };
DACB71791CC2D89D00432BD3 /* HeaderFooterController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderFooterController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -64,7 +68,8 @@
DAC2D5C71C9D3005009E9C19 /* Presentation */ = {
isa = PBXGroup;
children = (
DAC2D5D11C9D30D8009E9C19 /* Main */,
DACB71731CC2D5ED00432BD3 /* Controllers */,
DACB71741CC2D5FD00432BD3 /* Views */,
);
path = Presentation;
sourceTree = "<group>";
@ -96,22 +101,6 @@
path = Storyboards;
sourceTree = "<group>";
};
DAC2D5D11C9D30D8009E9C19 /* Main */ = {
isa = PBXGroup;
children = (
DAC2D5D21C9D30E4009E9C19 /* ViewControllers */,
);
path = Main;
sourceTree = "<group>";
};
DAC2D5D21C9D30E4009E9C19 /* ViewControllers */ = {
isa = PBXGroup;
children = (
DAC2D5D31C9D3118009E9C19 /* MainViewController.swift */,
);
path = ViewControllers;
sourceTree = "<group>";
};
DAC2D69A1C9E75BE009E9C19 /* Assets */ = {
isa = PBXGroup;
children = (
@ -120,6 +109,23 @@
path = Assets;
sourceTree = "<group>";
};
DACB71731CC2D5ED00432BD3 /* Controllers */ = {
isa = PBXGroup;
children = (
DACB71751CC2D63D00432BD3 /* MainController.swift */,
DACB71791CC2D89D00432BD3 /* HeaderFooterController.swift */,
);
path = Controllers;
sourceTree = "<group>";
};
DACB71741CC2D5FD00432BD3 /* Views */ = {
isa = PBXGroup;
children = (
DACB71771CC2D6ED00432BD3 /* StoryboardTableViewCell.swift */,
);
path = Views;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -192,8 +198,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DAC2D5D41C9D3118009E9C19 /* MainViewController.swift in Sources */,
DACB71781CC2D6ED00432BD3 /* StoryboardTableViewCell.swift in Sources */,
DACB71761CC2D63D00432BD3 /* MainController.swift in Sources */,
DAC2D5CA1C9D303E009E9C19 /* AppDelegate.swift in Sources */,
DACB717A1CC2D89D00432BD3 /* HeaderFooterController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -157,7 +157,7 @@ class TabletTests: XCTestCase {
let sectionHeaderView = UIView()
let sectionFooterView = UIView()
let section = TableSectionBuilder(headerView: sectionHeaderView, footerView: sectionFooterView)
let section = TableSectionBuilder(headerView: sectionHeaderView, footerView: sectionFooterView, rows: nil)
section += row
testController.view.hidden = false