Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for 'UITableViewController' #29

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 38 additions & 54 deletions Example/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,63 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6245" systemVersion="13E28" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="TiB-s5-4qI">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="TiB-s5-4qI">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6238"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Delicious Wines-->
<scene sceneID="ufC-wZ-h7g">
<!--View Controller-->
<scene sceneID="FF5-fk-Ii8">
<objects>
<viewController id="vXZ-lx-hvc" customClass="ViewController" customModule="Example" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="jyV-Pf-zRb"/>
<viewControllerLayoutGuide type="bottom" id="2fi-mo-0CV"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
<tableViewController id="Nrm-Tj-wRu" customClass="ViewController" customModule="Example" 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="K7k-Z4-l0h">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="4jG-2q-z2E">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="textCell" textLabel="VyT-JA-qNs" style="IBUITableViewCellStyleDefault" id="rHE-tw-gzT">
<rect key="frame" x="0.0" y="0.0" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="rHE-tw-gzT" id="sXh-T0-43a">
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="VyT-JA-qNs">
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="vXZ-lx-hvc" id="g6w-ar-DPT"/>
<outlet property="delegate" destination="vXZ-lx-hvc" id="C5J-VX-Y2i"/>
</connections>
</tableView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="4jG-2q-z2E" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" id="IjC-bB-MJc"/>
<constraint firstAttribute="trailing" secondItem="4jG-2q-z2E" secondAttribute="trailing" id="OgN-PF-mLQ"/>
<constraint firstItem="4jG-2q-z2E" firstAttribute="top" secondItem="kh9-bI-dsS" secondAttribute="top" id="R3a-4A-kIb"/>
<constraint firstItem="2fi-mo-0CV" firstAttribute="top" secondItem="4jG-2q-z2E" secondAttribute="bottom" id="q8O-Xk-dTi"/>
</constraints>
</view>
<navigationItem key="navigationItem" title="Delicious Wines" id="pzt-GG-U9n"/>
<connections>
<outlet property="tableView" destination="4jG-2q-z2E" id="mLX-q4-rQT"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
<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="textCell" textLabel="Xss-wN-f3S" style="IBUITableViewCellStyleDefault" id="YVf-5V-L6L">
<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="YVf-5V-L6L" id="pmD-YF-Hlw">
<rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Xss-wN-f3S">
<rect key="frame" x="15" y="0.0" width="570" height="43"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="Nrm-Tj-wRu" id="goG-gg-IAt"/>
<outlet property="delegate" destination="Nrm-Tj-wRu" id="kJf-uI-0lu"/>
</connections>
</tableView>
<navigationItem key="navigationItem" id="xQS-hT-0nV"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="6T2-lo-PuF" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="951" y="136"/>
<point key="canvasLocation" x="1013" y="136"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="Yu9-2B-bnR">
Expand All @@ -70,7 +54,7 @@
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="vXZ-lx-hvc" kind="relationship" relationship="rootViewController" id="7Vr-cN-eht"/>
<segue destination="Nrm-Tj-wRu" kind="relationship" relationship="rootViewController" id="5Ae-hw-ME3"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="DfM-km-PRZ" userLabel="First Responder" sceneMemberID="firstResponder"/>
Expand Down
15 changes: 4 additions & 11 deletions Example/PlaceholderViews/BasicPlaceholderView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,10 @@ class BasicPlaceholderView: UIView {
centerView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(centerView)

let views = ["centerView": centerView, "superview": self]
let vConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:[superview]-(<=1)-[centerView]",
options: .AlignAllCenterX,
metrics: nil,
views: views)
let hConstraints = NSLayoutConstraint.constraintsWithVisualFormat("H:[superview]-(<=1)-[centerView]",
options: .AlignAllCenterY,
metrics: nil,
views: views)
self.addConstraints(vConstraints)
self.addConstraints(hConstraints)
let vConstraint = NSLayoutConstraint(item: centerView, attribute: .CenterX, relatedBy: .Equal, toItem: self, attribute: .CenterX, multiplier: 1.0, constant: 0.0)
let hConstraint = NSLayoutConstraint(item: centerView, attribute: .CenterY, relatedBy: .Equal, toItem: self, attribute: .CenterY, multiplier: 1.0, constant: 0.0)
self.addConstraint(vConstraint)
self.addConstraint(hConstraint)
}

}
4 changes: 2 additions & 2 deletions Example/PlaceholderViews/EmptyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class EmptyView: BasicPlaceholderView {
override func setupView() {
super.setupView()

backgroundColor = UIColor.whiteColor()
backgroundColor = UIColor.blueColor()

label.text = "No Content."
label.translatesAutoresizingMaskIntoConstraints = false
Expand All @@ -26,7 +26,7 @@ class EmptyView: BasicPlaceholderView {
let vConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|-[label]-|", options: .AlignAllCenterX, metrics: nil, views: views)

centerView.addConstraints(hConstraints)
centerView.addConstraints(vConstraints)
centerView.addConstraints(vConstraints)
}

}
2 changes: 1 addition & 1 deletion Example/PlaceholderViews/LoadingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class LoadingView: BasicPlaceholderView, StatefulPlaceholderView {

centerView.addConstraints(hConstraints)
centerView.addConstraints(vConstraintsLabel)
centerView.addConstraints(vConstraintsActivity)
centerView.addConstraints(vConstraintsActivity)
}

func placeholderViewInsets() -> UIEdgeInsets {
Expand Down
43 changes: 23 additions & 20 deletions Example/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@
import UIKit
import StatefulViewController

class ViewController: UIViewController, StatefulViewController {
class ViewController: UITableViewController, StatefulViewController {
var dataArray = [String]()
let refreshControl = UIRefreshControl()
@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()

// Setup refresh control
refreshControl.addTarget(self, action: #selector(refresh), forControlEvents: .ValueChanged)
tableView.addSubview(refreshControl)
refreshControl = UIRefreshControl()
refreshControl?.addTarget(self, action: #selector(refresh), forControlEvents: .ValueChanged)

// Setup placeholder views
loadingView = LoadingView(frame: view.frame)
Expand All @@ -40,27 +38,27 @@ class ViewController: UIViewController, StatefulViewController {
if (lastState == .Loading) { return }

startLoading(completion: {
print("completaion startLoading -> loadingState: \(self.currentState.rawValue)")
print("completion startLoading -> loadingState: \(self.currentState.rawValue)")
})
print("startLoading -> loadingState: \(self.lastState.rawValue)")

// Fake network call
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(3 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
// Success
self.dataArray = ["Merlot", "Sauvignon Blanc", "Blaufränkisch", "Pinot Nior"]
self.tableView.reloadData()
self.endLoading(error: nil, completion: {
print("completion endLoading -> loadingState: \(self.currentState.rawValue)")
})
print("endLoading -> loadingState: \(self.lastState.rawValue)")
// self.dataArray = ["Merlot", "Sauvignon Blanc", "Blaufränkisch", "Pinot Nior"]
// self.tableView.reloadData()
// self.endLoading(error: nil, completion: {
// print("completion endLoading -> loadingState: \(self.currentState.rawValue)")
// })
// print("endLoading -> loadingState: \(self.lastState.rawValue)")

// Error
//self.endLoading(error: NSError(domain: "foo", code: -1, userInfo: nil))
// self.endLoading(error: NSError(domain: "foo", code: -1, userInfo: nil))

// No Content
//self.endLoading(error: nil)
self.endLoading(error: nil)

self.refreshControl.endRefreshing()
self.refreshControl?.endRefreshing()
}
}

Expand All @@ -82,16 +80,21 @@ extension ViewController {
}


extension ViewController: UITableViewDataSource {
extension ViewController {

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count + 1
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("textCell", forIndexPath: indexPath)
cell.textLabel?.text = dataArray[indexPath.row]
cell.textLabel?.text = "HELLO!"
// dataArray[indexPath.row]
return cell
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("CLICKED ROW!")
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ extension BackingViewProvider where Self: UIView {
}
}


// MARK: Default Implementation StatefulViewController

/// Default implementation of StatefulViewController for UIViewController
Expand Down Expand Up @@ -120,10 +119,21 @@ extension StatefulViewController {
}
}

extension StatefulViewController where Self: UITableViewController {

public var stateMachine: ViewStateMachine {
return associatedObject(self, key: &stateMachineKey) { [unowned self] in
return ContainerViewStateMachine(view: self.view)
}
}

}


// MARK: Association

private var stateMachineKey: UInt8 = 0
private var tableViewControllerStateContainerViewKey: UInt8 = 1

private func associatedObject<T: AnyObject>(host: AnyObject, key: UnsafePointer<Void>, initial: () -> T) -> T {
var value = objc_getAssociatedObject(host, key) as? T
Expand Down
53 changes: 52 additions & 1 deletion StatefulViewController/ViewStateMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public class ViewStateMachine {
newView.alpha = animated ? 0.0 : 1.0
newView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(newView)

let insets = (newView as? StatefulPlaceholderView)?.placeholderViewInsets() ?? UIEdgeInsets()
let metrics = ["top": insets.top, "bottom": insets.bottom, "left": insets.left, "right": insets.right]
let views = ["view": newView]
Expand Down Expand Up @@ -205,3 +205,54 @@ public class ViewStateMachine {
}
}
}

///
/// A state machine that manages a set of views by adding the state's view to a managed container view.
///
/// There are two possible states:
/// * Show a specific placeholder view, represented by a key
/// * Hide all managed views
///
public class ContainerViewStateMachine: ViewStateMachine {

private let containerSuperview: UIView

public override init(view: UIView, states: [String : UIView]?) {
self.containerSuperview = view

let containerView = StateViewContainerView(frame: self.containerSuperview.frame)
containerView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
containerView.backgroundColor = UIColor.clearColor()
containerView.layer.zPosition = self.containerSuperview.layer.zPosition + 1.0

super.init(view: containerView, states: states)
}

private override func showViewWithKey(state: String, animated: Bool, completion: (() -> ())?) {
self.view.frame = self.containerSuperview.frame
self.containerSuperview.addSubview(self.view)

super.showViewWithKey(state, animated: animated, completion: completion)
}

private override func hideAllViews(animated animated: Bool, completion: (() -> ())?) {
super.hideAllViews(animated: animated) {
completion?()
self.view.removeFromSuperview()
}
}
}

private class StateViewContainerView: UIView {

private override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
for view in self.subviews {
if !view.hidden && view.alpha > 0 && view.userInteractionEnabled &&
view.pointInside(self.convertPoint(point, toView:view), withEvent:event) {
return true
}
}
return false
}

}