Skip to content

Commit 5231c3e

Browse files
hlineholmDivineDominion
authored andcommitted
Rename Components of The Routable Protocol (#107)
* Rename `Segment` to `Element` * Rename `RoutingCompletionHandler` to `RoutingCompletion` * Reline Routable Protocol
1 parent 8269008 commit 5231c3e

File tree

7 files changed

+184
-194
lines changed

7 files changed

+184
-194
lines changed

Changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Upcoming
22

3+
**Breaking API Changes:**
4+
- Rename Components of the `Routable` protocol (#107) - @hlineholm
5+
6+
37
# 0.7.0
48

59
*Released: 2019-08-01*

README.md

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -84,66 +84,72 @@ This will make reducer handle all routing relevant actions.
8484

8585
# Implementing `Routable`
8686

87-
ReSwiftRouter works with routes that are defined, similar to URLs, as a sequence of identifiers e.g. `["Home", "User", "UserDetail"]`.
87+
ReSwiftRouter works with routes that are defined, similar to URLs, as a sequence of elements e.g. `["Home", "User", "UserDetail"]`.
8888

8989
ReSwiftRouter is agnostic of the UI framework you are using - it uses `Routable`s to implement that interaction.
9090

91-
Each route segment is mapped to one responsible `Routable`. The `Routable` needs to be able to present a child, hide a child or replace a child with another child.
91+
Each route element is mapped to one responsible `Routable`. The `Routable` needs to be able to present a child, hide a child or replace a child with another child.
9292

9393
Here is the `Routable` protocol with the methods you should implement:
9494

9595
```swift
96-
protocol Routable {
9796

98-
func changeRouteSegment(from: RouteElementIdentifier,
99-
to: RouteElementIdentifier,
100-
completionHandler: RoutingCompletionHandler) -> Routable
97+
public protocol Routable {
10198

102-
func pushRouteSegment(routeElementIdentifier: RouteElementIdentifier,
103-
completionHandler: RoutingCompletionHandler) -> Routable
99+
func push(
100+
_ element: RouteElement,
101+
animated: Bool,
102+
completion: @escaping RoutingCompletion) -> Routable
104103

105-
func popRouteSegment(routeElementIdentifier: RouteElementIdentifier,
106-
completionHandler: RoutingCompletionHandler)
104+
func pop(
105+
_ element: RouteElement,
106+
animated: Bool,
107+
completion: @escaping RoutingCompletion)
108+
109+
func change(
110+
_ from: RouteElement,
111+
to: RouteElement,
112+
animated: Bool,
113+
completion: @escaping RoutingCompletion) -> Routable
107114

108115
}
116+
109117
```
110118

111-
As part of initializing `Router` you need to pass the first `Routable` as an argument. That root `Routable` will be responsible for the first route segment.
119+
As part of initializing `Router` you need to pass the first `Routable` as an argument. That root `Routable` will be responsible for the first route element.
112120

113-
If e.g. you set the route of your application to `["Home"]`, your root `Routable` will be asked to present the view that corresponds to the identifier `"Home"`.
121+
If e.g. you set the route of your application to `["Home"]`, your root `Routable` will be asked to present the view that corresponds to the element `"Home"`.
114122

115123
When working on iOS with UIKit this would mean the `Routable` would need to set the `rootViewController` of the application.
116124

117-
Whenever a `Routable` presents a new route segment, it needs to return a new `Routable` that will be responsible for managing the presented segment. If you want to navigate from `["Home"]` to `["Home", "Users"]` the `Routable` responsible for the `"Home"` segment will be asked to present the `"User"` segment.
125+
Whenever a `Routable` presents a new route element, it needs to return a new `Routable` that will be responsible for managing the presented element. If you want to navigate from `["Home"]` to `["Home", "Users"]` the `Routable` responsible for the `"Home"` element will be asked to present the `"User"` element.
118126

119-
If your navigation stack uses a modal presentation for this transition, the implementation of `Routable` for the `"Home"` segment might look like this:
127+
If your navigation stack uses a modal presentation for this transition, the implementation of `Routable` for the `"Home"` element might look like this:
120128

121129
```swift
122-
func pushRouteSegment(identifier: RouteElementIdentifier,
123-
completionHandler: RoutingCompletionHandler) -> Routable {
124-
125-
if identifier == "User" {
130+
func push(_ element: RouteElement, animated: Bool, completion: @escaping RoutingCompletion) -> Routable {
131+
132+
if element == "User" {
126133
// 1.) Perform the transition
127134
userViewController = UIStoryboard(name: "Main", bundle: nil)
128135
.instantiateViewControllerWithIdentifier("UserViewController") as! Routable
129136

130-
// 2.) Call the `completionHandler` once the transition is complete
137+
// 2.) Call the `completion` once the transition is complete
131138
presentViewController(userViewController, animated: false,
132-
completion: completionHandler)
139+
completion: completion)
133140

134-
// 3.) Return the Routable for the presented segment. For convenience
141+
// 3.) Return the Routable for the presented element. For convenience
135142
// this will often be the UIViewController itself.
136143
return userViewController
137144
}
138145

139146
// ...
140147
}
141148

142-
func popRouteSegment(identifier: RouteElementIdentifier,
143-
completionHandler: RoutingCompletionHandler) {
149+
func pop(_ element: RouteElement, animated: Bool, completion: @escaping RoutingCompletion)
144150

145-
if identifier == "Home" {
146-
dismissViewControllerAnimated(false, completion: completionHandler)
151+
if element == "Home" {
152+
dismissViewControllerAnimated(false, completion: completion)
147153
}
148154

149155
// ...
@@ -152,7 +158,7 @@ func popRouteSegment(identifier: RouteElementIdentifier,
152158

153159
## Calling the Completion Handler within Routables
154160

155-
ReSwiftRouter needs to throttle the navigation actions, since many UI frameworks including UIKit don't allow to perform multiple navigation steps in parallel. Therefor every method of `Routable` receives a `completionHandler`. The router will not perform any further navigation actions until the completion handler is called.
161+
ReSwiftRouter needs to throttle the navigation actions, since many UI frameworks including UIKit don't allow to perform multiple navigation steps in parallel. Therefor every method of `Routable` receives a `completion` handler. The router will not perform any further navigation actions until the completion handler is called.
156162

157163
# Changing the Current Route
158164

@@ -165,7 +171,7 @@ Currently the only way to change the current application route is by using the `
165171
)
166172
}
167173
```
168-
As development continues, support for changing individual route segments will be added.
174+
As development continues, support for changing individual route elements will be added.
169175

170176

171177
# Contributing

ReSwiftRouter/NavigationState.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
import ReSwift
1010

11-
public typealias RouteElementIdentifier = String
12-
public typealias Route = [RouteElementIdentifier]
11+
public typealias RouteElement = String
12+
public typealias Route = [RouteElement]
1313

1414
/// A `Hashable` and `Equatable` presentation of a route.
1515
/// Can be used to check two routes for equality.

ReSwiftRouter/Routable.swift

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,50 +6,30 @@
66
// Copyright © 2015 DigiTales. All rights reserved.
77
//
88

9-
public typealias RoutingCompletionHandler = () -> Void
9+
public typealias RoutingCompletion = () -> Void
1010

1111
public protocol Routable {
1212

13-
func pushRouteSegment(
14-
_ routeElementIdentifier: RouteElementIdentifier,
15-
animated: Bool,
16-
completionHandler: @escaping RoutingCompletionHandler) -> Routable
13+
func push(_ element: RouteElement, animated: Bool, completion: @escaping RoutingCompletion) -> Routable
1714

18-
func popRouteSegment(
19-
_ routeElementIdentifier: RouteElementIdentifier,
20-
animated: Bool,
21-
completionHandler: @escaping RoutingCompletionHandler)
15+
func pop(_ element: RouteElement, animated: Bool, completion: @escaping RoutingCompletion)
2216

23-
func changeRouteSegment(
24-
_ from: RouteElementIdentifier,
25-
to: RouteElementIdentifier,
26-
animated: Bool,
27-
completionHandler: @escaping RoutingCompletionHandler) -> Routable
17+
func change(_ from: RouteElement, to: RouteElement, animated: Bool, completion: @escaping RoutingCompletion) -> Routable
2818

2919
}
3020

3121
extension Routable {
3222

33-
public func pushRouteSegment(
34-
_ routeElementIdentifier: RouteElementIdentifier,
35-
animated: Bool,
36-
completionHandler: @escaping RoutingCompletionHandler) -> Routable {
37-
fatalError("This routable cannot push segments. You have not implemented it. (Asked \(type(of: self)) to push \(routeElementIdentifier))")
23+
public func push(_ element: RouteElement, animated: Bool, completion: @escaping RoutingCompletion) -> Routable {
24+
fatalError("This routable cannot push elements. You have not implemented it. (Asked \(type(of: self)) to push \(element))")
3825
}
3926

40-
public func popRouteSegment(
41-
_ routeElementIdentifier: RouteElementIdentifier,
42-
animated: Bool,
43-
completionHandler: @escaping RoutingCompletionHandler) {
44-
fatalError("This routable cannot pop segments. You have not implemented it. (Asked \(type(of: self)) to pop \(routeElementIdentifier))")
27+
public func pop(_ element: RouteElement, animated: Bool, completion: @escaping RoutingCompletion) {
28+
fatalError("This routable cannot pop elements. You have not implemented it. (Asked \(type(of: self)) to pop \(element))")
4529
}
4630

47-
public func changeRouteSegment(
48-
_ from: RouteElementIdentifier,
49-
to: RouteElementIdentifier,
50-
animated: Bool,
51-
completionHandler: @escaping RoutingCompletionHandler) -> Routable {
52-
fatalError("This routable cannot change segments. You have not implemented it. (Asked \(type(of: self)) to change from \(from) to \(to))")
31+
public func change(_ from: RouteElement, to: RouteElement, animated: Bool, completion: @escaping RoutingCompletion) -> Routable {
32+
fatalError("This routable cannot change elements. You have not implemented it. (Asked \(type(of: self)) to change from \(from) to \(to))")
5333
}
5434

5535
}

ReSwiftRouter/Router.swift

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -40,36 +40,36 @@ open class Router<State: StateType>: StoreSubscriber {
4040
waitForRoutingCompletionQueue.async {
4141
switch routingAction {
4242

43-
case let .pop(responsibleRoutableIndex, segmentToBePopped):
43+
case let .pop(responsibleRoutableIndex, elementToBePopped):
4444
DispatchQueue.main.async {
4545
self.routables[responsibleRoutableIndex]
46-
.popRouteSegment(
47-
segmentToBePopped,
46+
.pop(
47+
elementToBePopped,
4848
animated: state.changeRouteAnimated) {
4949
semaphore.signal()
5050
}
5151

5252
self.routables.remove(at: responsibleRoutableIndex + 1)
5353
}
5454

55-
case let .change(responsibleRoutableIndex, segmentToBeReplaced, newSegment):
55+
case let .change(responsibleRoutableIndex, elementToBeReplaced, newElement):
5656
DispatchQueue.main.async {
5757
self.routables[responsibleRoutableIndex + 1] =
5858
self.routables[responsibleRoutableIndex]
59-
.changeRouteSegment(
60-
segmentToBeReplaced,
61-
to: newSegment,
59+
.change(
60+
elementToBeReplaced,
61+
to: newElement,
6262
animated: state.changeRouteAnimated) {
6363
semaphore.signal()
6464
}
6565
}
6666

67-
case let .push(responsibleRoutableIndex, segmentToBePushed):
67+
case let .push(responsibleRoutableIndex, elementToBePushed):
6868
DispatchQueue.main.async {
6969
self.routables.append(
7070
self.routables[responsibleRoutableIndex]
71-
.pushRouteSegment(
72-
segmentToBePushed,
71+
.push(
72+
elementToBePushed,
7373
animated: state.changeRouteAnimated) {
7474
semaphore.signal()
7575
}
@@ -114,8 +114,8 @@ open class Router<State: StateType>: StoreSubscriber {
114114
// is not represented in the route, e.g.
115115
// route = ["tabBar"]
116116
// routables = [RootRoutable, TabBarRoutable]
117-
static func routableIndex(for segment: Int) -> Int {
118-
return segment + 1
117+
static func routableIndex(for element: Int) -> Int {
118+
return element + 1
119119
}
120120

121121
static func routingActionsForTransition(
@@ -134,22 +134,22 @@ open class Router<State: StateType>: StoreSubscriber {
134134
// We start at the end of the old route
135135
var routeBuildingIndex = oldRoute.count - 1
136136

137-
// Pop all route segments of the old route that are no longer in the new route
137+
// Pop all route elements of the old route that are no longer in the new route
138138
// Stop one element ahead of the commonSubroute. When we are one element ahead of the
139139
// commmon subroute we have three options:
140140
//
141141
// 1. The old route had an element after the commonSubroute and the new route does not
142-
// we need to pop the route segment after the commonSubroute
142+
// we need to pop the route element after the commonSubroute
143143
// 2. The old route had no element after the commonSubroute and the new route does, we
144-
// we need to push the route segment(s) after the commonSubroute
144+
// we need to push the route element(s) after the commonSubroute
145145
// 3. The new route has a different element after the commonSubroute, we need to replace
146146
// the old route element with the new one
147147
while routeBuildingIndex > commonSubroute + 1 {
148-
let routeSegmentToPop = oldRoute[routeBuildingIndex]
148+
let routeElementToPop = oldRoute[routeBuildingIndex]
149149

150150
let popAction = RoutingActions.pop(
151151
responsibleRoutableIndex: routableIndex(for: routeBuildingIndex - 1),
152-
segmentToBePopped: routeSegmentToPop
152+
elementToBePopped: routeElementToPop
153153
)
154154

155155
routingActions.append(popAction)
@@ -162,18 +162,18 @@ open class Router<State: StateType>: StoreSubscriber {
162162
if oldRoute.count > (commonSubroute + 1) && newRoute.count > (commonSubroute + 1) {
163163
let changeAction = RoutingActions.change(
164164
responsibleRoutableIndex: routableIndex(for: commonSubroute),
165-
segmentToBeReplaced: oldRoute[commonSubroute + 1],
166-
newSegment: newRoute[commonSubroute + 1])
165+
elementToBeReplaced: oldRoute[commonSubroute + 1],
166+
newElement: newRoute[commonSubroute + 1])
167167

168168
routingActions.append(changeAction)
169169
}
170170
// This is the 1. case:
171171
// "The old route had an element after the commonSubroute and the new route does not
172-
// we need to pop the route segment after the commonSubroute"
172+
// we need to pop the route element after the commonSubroute"
173173
else if oldRoute.count > newRoute.count {
174174
let popAction = RoutingActions.pop(
175175
responsibleRoutableIndex: routableIndex(for: routeBuildingIndex - 1),
176-
segmentToBePopped: oldRoute[routeBuildingIndex]
176+
elementToBePopped: oldRoute[routeBuildingIndex]
177177
)
178178

179179
routingActions.append(popAction)
@@ -184,15 +184,15 @@ open class Router<State: StateType>: StoreSubscriber {
184184
// Push remainder of elements in new Route that weren't in old Route, this covers
185185
// the 2. case:
186186
// "The old route had no element after the commonSubroute and the new route does,
187-
// we need to push the route segment(s) after the commonSubroute"
187+
// we need to push the route element(s) after the commonSubroute"
188188
let newRouteIndex = newRoute.count - 1
189189

190190
while routeBuildingIndex < newRouteIndex {
191-
let routeSegmentToPush = newRoute[routeBuildingIndex + 1]
191+
let routeElementToPush = newRoute[routeBuildingIndex + 1]
192192

193193
let pushAction = RoutingActions.push(
194194
responsibleRoutableIndex: routableIndex(for: routeBuildingIndex),
195-
segmentToBePushed: routeSegmentToPush
195+
elementToBePushed: routeElementToPush
196196
)
197197

198198
routingActions.append(pushAction)
@@ -207,8 +207,8 @@ open class Router<State: StateType>: StoreSubscriber {
207207
func ReSwiftRouterStuck() {}
208208

209209
enum RoutingActions {
210-
case push(responsibleRoutableIndex: Int, segmentToBePushed: RouteElementIdentifier)
211-
case pop(responsibleRoutableIndex: Int, segmentToBePopped: RouteElementIdentifier)
212-
case change(responsibleRoutableIndex: Int, segmentToBeReplaced: RouteElementIdentifier,
213-
newSegment: RouteElementIdentifier)
210+
case push(responsibleRoutableIndex: Int, elementToBePushed: RouteElement)
211+
case pop(responsibleRoutableIndex: Int, elementToBePopped: RouteElement)
212+
case change(responsibleRoutableIndex: Int, elementToBeReplaced: RouteElement,
213+
newElement: RouteElement)
214214
}

0 commit comments

Comments
 (0)