Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/limboy/elf
a lightweight, pure-swift router for url handling
https://github.com/limboy/elf
ios router routing swift
Last synced: 5 days ago
JSON representation
a lightweight, pure-swift router for url handling
- Host: GitHub
- URL: https://github.com/limboy/elf
- Owner: limboy
- License: mit
- Created: 2019-02-04T16:34:16.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2019-02-04T17:15:49.000Z (almost 6 years ago)
- Last Synced: 2024-05-02T06:08:59.702Z (8 months ago)
- Topics: ios, router, routing, swift
- Language: Swift
- Homepage:
- Size: 50.8 KB
- Stars: 11
- Watchers: 3
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Elf
![Swift](https://img.shields.io/badge/Swift-4.2-orange.svg)
![Cocoapods](https://img.shields.io/cocoapods/v/Elf.svg?style=flat)Elf is a lightweight, pure-swift router for url handling. Make incoming url find the right handler. that's all Elf do.
![Elf Workflow](https://user-images.githubusercontent.com/35974/52165604-eb8ebf80-273d-11e9-8786-d344f605ff9b.png)
So what is a handler?
```swift
protocol Handler: class {
func convert(params:Dictionary, queryParams: Dictionary)
func handle()
}
```if Elf find the right handler, it will first call `convert` method with `params` and `queryParams`. Within this method, these params can be converted to internal properties.
`handle()` will be called next. you can do all stuff here. like build a View Controller, push it or present it, or just make a switch on based on incoming params, or popup an alert window, etc.
## Getting Started
First Let's create some handlers.
```swift
class ProfileHandler:Handler {
var profileID: String?func convert(params: Dictionary, queryParams: Dictionary) {
profileID = queryParams["id"]
}
func handle() {
if let id = profileID {
let vc = ProfileViewController()
vc.profileID = id
navigationController.push(vc)
} else {
// present error page
}
}
}class UserHandler:Handler {
var username: String?func convert(params: Dictionary, queryParams: Dictionary) {
username = params["username"]
}
func handle() {
if let id = username {
let vc = UserFollowingViewController()
navigationController.push(vc)
}
}
}
```Then connect these handlers with appropriate url patterns.
```swift
let routeTable:[String:Handler] = [
"app://profile": ProfileHandler(),
"app://user/{username}/following": UserHandler(),
]Elf.instance.registerRoutingTable(routeTable, notFoundHandler: {url in print("\(url) not found")})
```Now let's handle urls!
```swift
// for test case
Elf.instance.handleURL(url: "app://profile?id=1024")
Elf.instance.handleURL(url: "app://user/limboy/following")// usually it should be put in `AppDelegate's` method
func application(_ application: UIApplication,
open url: URL,
sourceApplication: String?,
annotation: Any) -> Bool {// ...
Elf.instance.handleURL(url: url.absoluteString)
}
```if Elf found url's pattern in registered table, target handler will be triggered, else `notFoundHandler` will be called, in there a custom ViewController can be presented.
## Installation
### Podfile
```
pod 'Elf'
```## Scenarios
### Push a viewcontroller
for example, tap an item in `ShopItemListViewController`, a `DetailViewController` should be pushed. it can be done like this:
```swift
let handler = DetailHandler()
handler.id = 1024
handler.handle()
````DetailHandler` is used as an entry/wrapper for `DetailViewController`, no matter it's came from url or called internally. both handled in a universal way.
So you don't have to open target View Controller, trying to find out what's needed to init. It's also flexible for `DetailViewController` if some properties should be changed as long as `DetailHandler` is not affected.
### Pinterest Style
When a Pinterest's waterfall list item is tapped, its model will be passed to detail page, so it won't be blank at first. but when opened by url, no model will be passed in. These two scenarios are all handled by `DetailHandler`.
```swift
class DetailHandler:Handler {
var itemModel: ItemModel?
var itemID: String?func convert(params: Dictionary, queryParams: Dictionary) {
itemID = params["id"]
}
func handle() {
// opened internal
if let model = itemModel {
let vc = DetailViewController()
vc.model = itemModel
navigationController.push(vc)
return
}// opened by url
if let id = itemID {
let vc = DetailViewController()
vc.id = itemID
navigationController.push(vc)
}
}
}
```When the basic model is filled or user has made some change, previous View Controller should know, and update accordingly. just add a property like `onModelUpdate()`, when model is updated just call this function (if it not nil).
## Router Design
URL patterns are stored in a radix like tree, it will first split incoming url into sections, then match them one by one through the tree.## Tips
* to keep things simple, url pattern only match to `String`. `app://profile/{id}` will get `params["id"]` as `String` in `convert` method.
* a navigator can be injected into `Handler`'s child protocol, to make it easier to navigate.
* `SomeHandler` can be used to act as a config handler, when opened by url like `?debugcode=xxx`, debug mode is on.## Contact
Follow and contact me on [Twitter](https://twitter.com/lzyy). If you find an issue, just open a ticket. Pull requests are warmly welcome as well.
## License
Elf is released under the MIT license. See LICENSE for details.