Skip to content

Commit c2c1e1a

Browse files
committed
introducing a lastState property and completion handlers when the current state changes (fixes #5)
1 parent e243986 commit c2c1e1a

3 files changed

Lines changed: 56 additions & 37 deletions

File tree

Example/ViewController.swift

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,28 @@ class ViewController: StatefulViewController {
3030
}
3131

3232
override func viewWillAppear(animated: Bool) {
33+
refresh()
34+
3335
super.viewWillAppear(animated)
34-
35-
refresh()
3636
}
3737

3838
func refresh() {
39-
if (currentState == .Loading) { return }
40-
startLoading()
39+
if (lastState == .Loading) { return }
40+
41+
startLoading(completion: {
42+
println("completaion startLoading -> loadingState: \(self.currentState.rawValue)")
43+
})
44+
println("startLoading -> loadingState: \(self.lastState.rawValue)")
4145

4246
// Fake network call
43-
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
47+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(3 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
4448
// Success
4549
self.dataArray = ["Merlot", "Sauvignon Blanc", "Blaufränkisch", "Pinot Nior"]
4650
self.tableView.reloadData()
47-
self.endLoading(error: nil)
51+
self.endLoading(error: nil, completion: {
52+
println("completion endLoading -> loadingState: \(self.currentState.rawValue)")
53+
})
54+
println("endLoading -> loadingState: \(self.lastState.rawValue)")
4855
self.refreshControl.endRefreshing()
4956

5057
// Error

StatefulViewController/StatefulViewController.swift

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,17 @@ public class StatefulViewController: UIViewController {
4343
/// All states other than `Content` imply that there is a placeholder view shown.
4444
public var currentState: StatefulViewControllerState {
4545
switch stateMachine.currentState {
46-
case .None: return .Content
47-
case .View(let viewKey): return StatefulViewControllerState(rawValue: viewKey)!
46+
case .None: return .Content
47+
case .View(let viewKey): return StatefulViewControllerState(rawValue: viewKey)!
4848
}
4949
}
5050

51+
public var lastState: StatefulViewControllerState {
52+
switch stateMachine.currentState {
53+
case .None: return .Content
54+
case .View(let viewKey): return StatefulViewControllerState(rawValue: viewKey)!
55+
}
56+
}
5157

5258
// MARK: Views
5359

@@ -71,8 +77,11 @@ public class StatefulViewController: UIViewController {
7177

7278
override public func viewWillAppear(animated: Bool) {
7379
super.viewWillAppear(animated)
74-
75-
transitionViewStates(animated: false)
80+
81+
// Make sure to stay in the correct state when transitioning
82+
let isLoading = (currentState == .Loading)
83+
let error: NSError? = (currentState == .Error) ? NSError() : nil
84+
transitionViewStates(loading: isLoading, error: error, animated: false)
7685
}
7786

7887

@@ -83,8 +92,8 @@ public class StatefulViewController: UIViewController {
8392
///
8493
/// :param: animated true if the switch to the placeholder view should be animated, false otherwise
8594
///
86-
public func startLoading(animated: Bool = false) {
87-
transitionViewStates(loading: true, animated: animated)
95+
public func startLoading(animated: Bool = false, completion: (() -> ())? = nil) {
96+
transitionViewStates(loading: true, animated: animated, completion: completion)
8897
}
8998

9099
/// Ends the controller's loading state.
@@ -94,8 +103,8 @@ public class StatefulViewController: UIViewController {
94103
/// :param: animated true if the switch to the placeholder view should be animated, false otherwise
95104
/// :param: error An error that might have occured whilst loading
96105
///
97-
public func endLoading(animated: Bool = true, error: NSError? = nil) {
98-
transitionViewStates(loading: false, animated: animated, error: error)
106+
public func endLoading(animated: Bool = true, error: NSError? = nil, completion: (() -> ())? = nil) {
107+
transitionViewStates(loading: false, animated: animated, error: error, completion: completion)
99108
}
100109

101110

@@ -108,29 +117,27 @@ public class StatefulViewController: UIViewController {
108117
/// :param: error An error that might have occured whilst loading
109118
/// :param: animated true if the switch to the placeholder view should be animated, false otherwise
110119
///
111-
public func transitionViewStates(loading: Bool = false, error: NSError? = nil, animated: Bool = true) {
112-
dispatch_async(dispatch_get_main_queue()) {
113-
let hasContent = (self as? StatefulViewControllerDelegate)?.hasContent() ?? true
114-
115-
// Update view for content (i.e. hide all placeholder views)
116-
if hasContent {
117-
if let e = error {
118-
// show unobstrusive error
119-
(self as? StatefulViewControllerDelegate)?.handleErrorWhenContentAvailable?(e)
120-
}
121-
self.stateMachine.transitionToState(.None, animated: animated)
122-
return
123-
}
124-
125-
// Update view for placeholder
126-
var newState: StatefulViewControllerState = .Empty
127-
if loading {
128-
newState = .Loading
129-
} else if let e = error {
130-
newState = .Error
131-
}
132-
self.stateMachine.transitionToState(.View(newState.rawValue), animated: animated)
133-
}
120+
public func transitionViewStates(loading: Bool = false, error: NSError? = nil, animated: Bool = true, completion: (() -> ())? = nil) {
121+
let hasContent = (self as? StatefulViewControllerDelegate)?.hasContent() ?? true
122+
123+
// Update view for content (i.e. hide all placeholder views)
124+
if hasContent {
125+
if let e = error {
126+
// show unobstrusive error
127+
(self as? StatefulViewControllerDelegate)?.handleErrorWhenContentAvailable?(e)
128+
}
129+
self.stateMachine.transitionToState(.None, animated: animated, completion: completion)
130+
return
131+
}
132+
133+
// Update view for placeholder
134+
var newState: StatefulViewControllerState = .Empty
135+
if loading {
136+
newState = .Loading
137+
} else if let e = error {
138+
newState = .Error
139+
}
140+
self.stateMachine.transitionToState(.View(newState.rawValue), animated: animated, completion: completion)
134141
}
135142

136143

StatefulViewController/ViewStateMachine.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ public class ViewStateMachine {
4141
/// The current display state of views
4242
public private(set) var currentState: ViewStateMachineState = .None
4343

44+
/// The last state that was enqueued
45+
public private(set) var lastState: ViewStateMachineState = .None
4446

47+
4548
// MARK: Init
4649

4750
/// Designated initializer.
@@ -109,6 +112,8 @@ public class ViewStateMachine {
109112
/// :param: campletion called when all animations are finished and the view has been updated
110113
///
111114
public func transitionToState(state: ViewStateMachineState, animated: Bool = true, completion: (() -> ())? = nil) {
115+
lastState = state
116+
112117
dispatch_async(queue) {
113118
if state == self.currentState {
114119
return

0 commit comments

Comments
 (0)