Skip to content
This repository has been archived by the owner on Oct 10, 2024. It is now read-only.

Commit

Permalink
View controller visit proposal extensions (#55)
Browse files Browse the repository at this point in the history
* Add view controller as a first-citizen in visit proposal

* Rename identification protocol

* Extend VisitableViewController so we can return a default value for view controller

* Add documentation to view controller property and PathConfigurationIdentifiable

* Update read me

* Add best practice on identifier

* Update README.md

Formatting

* Documentation tweaks

* Code formatting

---------

Co-authored-by: Joe Masilotti <[email protected]>
  • Loading branch information
olivaresf and joemasilotti authored Sep 29, 2023
1 parent d980904 commit 159a2ef
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
38 changes: 35 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,14 +227,25 @@ It shows off most of the navigation flows outlined above. There is also an examp

You can also implement an optional method on the `TurboNavigationDelegate` to handle custom routing.

This is useful to break out of the default behavior and/or render a native screen.
This is useful to break out of the default behavior and/or render a native screen. You may inspect the provided proposal and decide routing based on any of its properties. For custom native screens, you may also include a `"view-controller"` property that will be passed along.

```json
{
"patterns": [
"/numbers$"
],
"properties": {
"view-controller": "numbers"
}
}
```

```swift
class MyCustomClass: TurboNavigationDelegate {
let navigator = TurboNavigator(delegate: self)

func controller(_ controller: VisitableViewController, forProposal proposal: VisitProposal) -> UIViewController? {
if proposal.url.path == "/numbers" {
func handle(proposal: VisitProposal) -> ProposalResult {
if proposal.viewController == "numbers" {
// Let Turbo Navigator route this custom controller.
return NumbersViewController()
} else if proposal.presentation == .clearAll {
Expand All @@ -250,6 +261,27 @@ class MyCustomClass: TurboNavigationDelegate {
}
```

If you're relying on the `"view-controller"` property, we recommend your view controllers conform to `PathConfigurationIdentifiable`. You should also avoid using the class name as identifier, as you might rename your controller in the future.

```swift
class NumbersViewController: UIViewController, PathConfigurationIdentifiable {
static var pathConfigurationIdentifier: String { "numbers" }
}

class MyCustomClass: TurboNavigationDelegate {
let navigator = TurboNavigator(delegate: self)

func handle(proposal: VisitProposal) -> ProposalResult {
if proposal.viewController == NumbersViewController.pathConfigurationIdentifier {
// Let Turbo Navigator route this custom controller.
return NumbersViewController()
} else ...
...
}
}
}
```

## Custom configuration

Customize the configuration via `TurboConfig`.
Expand Down
18 changes: 18 additions & 0 deletions Sources/PathConfigurationIdentifiable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import UIKit

/// As a convenience, your view controller may conform to `PathConfigurationIdentifiable`.
/// You may then use the view controller's `pathConfigurationIdentifier` property instead of `proposal.url` when deciding how to handle a proposal. See `VisitProposal.viewController` on how to use this in your configuration file.
///
/// ```
/// func handle(proposal: VisitProposal) -> ProposalResult {
/// switch proposal.viewController {
/// case RecipeViewController.pathConfigurationIdentifier:
/// return .accept(RecipeViewController.new)
/// default:
/// return .accept
/// }
/// }
/// ```
public protocol PathConfigurationIdentifiable: UIViewController {
static var pathConfigurationIdentifier: String { get }
}
30 changes: 30 additions & 0 deletions Sources/VisitProposalExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,34 @@ public extension VisitProposal {
}
return .default
}

/// Used to identify a custom native view controller if provided in the path configuration properties of a given pattern.
///
/// For example, given the following configuration file:
///
/// ```
/// {
/// "rules": [
/// {
/// "patterns": [
/// "/recipes/*"
/// ],
/// "properties": {
/// "view-controller": "recipes",
/// }
/// }
/// ]
/// }
/// ```
///
/// A VisitProposal to `https://example.com/recipes/` will have `proposal.viewController == "recipes"`
///
/// A default value is provided in case the view controller property is missing from the configuration file. This will route the default `VisitableViewController`.
var viewController: String {
if let viewController = properties["view-controller"] as? String {
return viewController
}

return VisitableViewController.pathConfigurationIdentifier
}
}
5 changes: 5 additions & 0 deletions Sources/VisitableViewControllerExtension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Turbo

extension VisitableViewController: PathConfigurationIdentifiable {
public static var pathConfigurationIdentifier: String { "web" }
}

0 comments on commit 159a2ef

Please sign in to comment.