📱
📲
CoreNavigation Navigate between view controllers with ease.
Getting Started
These instructions will help you integrate CoreNavigation into your project.
Prerequisities
- Xcode 9 or higher
- iOS 8 or higher
- Cocoapods
Installation
CocoaPods
CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:
$ gem install cocoapods
CocoaPods 1.1+ is required to build CoreNavigation 1.0+.
To integrate CoreNavigation into your Xcode project using CocoaPods, specify it in your Podfile:
target '
'
do
use_frameworks!
pod 'CoreNavigation', '1.0.0-beta-4'
end
Then, run the following command:
$ pod install
Carthage
Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
You can install Carthage with Homebrew using the following command:
$ brew update
$ brew install carthage
To integrate CoreNavigation into your Xcode project using Carthage, specify it in your Cartfile:
github "aronbalog/CoreNavigation" == "1.0.0-beta-4"
API Reference
API reference
Example Use
Defining view controller:
class PersonProfileViewController: UIViewController, DataReceivable {
// DataReceivable associatedtype
typealias DataType = Person
func didReceiveData(_ data: Person) {
// configure UI with data
}
}
Presenting view controller:
Navigate.present { $0
.to(PersonProfileViewController())
.withData(person)
}
Pushing view controller:
Navigate.push { $0
.to(PersonProfileViewController())
.withData(person)
}
Routing & deep linking:
Why use the Destination
instead navigating directly to view controller?
Read about it on Medium:
- #0 present & push… For how long?
- #1 Forget about segues.
- #2 Passing data between view controllers.
- #3 Handle Universal Links Like a Boss.
Destination
Defining
struct PersonProfile: Destination, Routable {
// Destination associatedtype
typealias ViewControllerType = PersonProfileViewController
// Routable patterns
static var patterns: [String] = [
"https://myapp.com/person/:personId(.*)",
"https://myapp.com/user/:personId(.*)"
]
let personId: String
init(_ personId: String) {
self.personId = personId
}
var parameters: [String : Any]? {
return [
"personId": personId
]
}
static func resolve(context: Context
) {
guard
let personId
= context.
parameters
?[
"personId"]
as?
String
else {
// cancel navigation with some error
context.
cancel(
error: NavigationError.
Destination.
notFound)
return
}
// fetch person
fetchPerson(
id: personId,
completion: { (
person: Person)
in
// continue to navigation
context.
complete(
data: person)
},
failure: { (
error:
Error)
in
// cancel navigation with some error
context.
cancel(
error: error)
})
}
}
Routable
types
Registering In order to use Matchable
types (String
, URL
, etc.) to navigate, every Destination
type must be registered. Think about it as internal DNS.
PersonProfile.register()
Additional syntax
Navigate.router.register(routableType: PersonProfile.self)
Destination
type can be routable without conforming to Routable
protocol. Use this if you intend to create some kind of destination manifest and/or if route patterns are fetched from an external source:
Navigate.router.register(destinationType: PersonProfile.self, patterns: [
"https://myapp.com/person/:personId(.*)",
"https://myapp.com/user/:personId(.*)"
])
Additional syntax
PersonProfile.self <- [
"https://myapp.com/person/:personId(.*)",
"https://myapp.com/user/:personId(.*)"
]
Settings.self <- [
"https://myapp.com/settings"
]
Destination
Navigating using // present
Navigate.present { $0
.to(PersonProfile("sherlock_holmes"))
...
}
// or push
Navigate.push { $0
.to(PersonProfile("sherlock_holmes"))
...
}
Additional syntax
// present
PersonProfile("sherlock_holmes").present { $0
...
}
// or push
PersonProfile("sherlock_holmes").push { $0
...
}
Additional syntax
// present
PersonProfile("sherlock_holmes").present()
// or push
PersonProfile("sherlock_holmes").push()
Navigating using route
// present
Navigate.present { $0
.to("https://myapp.com/person/sherlock_holmes")
...
}
// or push
Navigate.push { $0
.to("https://myapp.com/person/sherlock_holmes")
...
}
Additional syntax
// present
"https://myapp.com/person/sherlock_holmes".present { $0
...
}
// or push
"https://myapp.com/person/sherlock_holmes".push { $0
...
}
Additional syntax
// present
"https://myapp.com/person/sherlock_holmes".present()
// or push
"https://myapp.com/person/sherlock_holmes".push()
Destination
Getting view controller asynchronously using PersonProfile("sherlock_holmes").viewController { (viewController) in
// vc is `PersonProfileViewController`
}
Getting view controller asynchronously using route
"https://myapp.com/person/sherlock_holmes".viewController { (viewController) in
...
}
Destination
Getting view controller synchronously using
do {
let viewController = try PersonProfile("sherlock_holmes").viewController()
} catch let error {
// handle error
}
Getting view controller synchronously using route
do {
let viewController = try "https://myapp.com/person/sherlock_holmes".viewController()
} catch let error {
// handle error
}
Note:
If you implement custom destination resolving, it must happen on the main thread; otherwise, an error is thrown.
Matchable protocol
URL
types can also be used to navigate or resolve view controller. Actually, any type conforming Matchable
protocol can be used.
Conforming to matchable:
struct Person {
let id: String
...
}
extension Person: Matchable {
var uri: String {
return "https://myapp.com/person/" + id
}
}
Example usage:
let person: Person = Person(id: "sherlock_holmes", ...)
// getting view controller
let personProfileViewController = try! person.viewController
// or navigating
person.present()
person.push()
// or more configurable syntax
Navigate.present { $0
.to(person)
...
}
Configuration
- Animating
- Observing completion
- Observing success
- Observing failure
- Embedding
- Passing data
- Caching
- Protection
- State restoration
- Specifying origin view controller
Example Apps
Running the Tests
Available in CoreNavigationTests
target.
Versioning
Current release:
- 1.0.0-beta-4
Authors
Contributing
Please read Contributing for details on code of conduct, and the process for submitting pull requests.
License
This project is licensed under the MIT License - see the LICENSE file for details.