Elf
Elf是一个轻量级的纯Swift路由,用于处理URL。使传入的URL能够找到正确的处理器。这就是Elf所做的一切。
那么处理器是什么意思呢?
protocol Handler: class {
func convert(params:Dictionary<String, String>, queryParams: Dictionary<String, String>)
func handle()
}
如果Elf找到了正确的处理器,它将会先调用convert
方法,传入params
和queryParams
。在这个方法中,这些参数可以被转换为内部属性。
接下来将调用handle
方法。您可以在其中做所有事情。例如构建一个View Controller, pushes它或者present它,或者根据传入的参数执行一个切换,或者弹出警告窗口等。
入门指南
首先让我们创建一些处理器。
class ProfileHandler:Handler {
var profileID: String?
func convert(params: Dictionary<String, String>, queryParams: Dictionary<String, String>) {
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<String, String>, queryParams: Dictionary<String, String>) {
username = params["username"]
}
func handle() {
if let id = username {
let vc = UserFollowingViewController()
navigationController.push(vc)
}
}
}
然后使用适当的URL模式连接这些处理器。
let routeTable:[String:Handler] = [
"app://profile": ProfileHandler(),
"app://user/{username}/following": UserHandler(),
]
Elf.instance.registerRoutingTable(routeTable, notFoundHandler: {url in print("\(url) not found")})
现在让我们处理这些URL!
// 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)
}
如果Elf在注册表中找到了URL模式,目标处理器将被触发,否则将调用notFoundHandler
,在那里可以present一个自定义ViewController。
安装
Podfile
pod 'Elf'
场景
推送 viewcontroller
例如,在 ShopItemListViewController
中点击一个项目,应推送一个 DetailViewController
。可以这样做:
let handler = DetailHandler()
handler.id = 1024
handler.handle()
DetailHandler
被用作 DetailViewController
的入口/包装,无论它来自 URL 还是内部调用。两者都以统一的方式进行处理。
因此,你不需要打开目标 View Controller,尝试找出初始化时需要什么。这也在 DetailHandler
未受影响的情况下,为 DetailViewController
提供了灵活性,如果需要改变某些属性。
Pinterest 样式
当 Pinterest 的瀑布列表项目被点击时,其模型将传递到详情页面,因此不会一开始就是空的。但是当通过 URL 打开时,不会有模型传递。这两种情况都由 DetailHandler
处理。
class DetailHandler:Handler {
var itemModel: ItemModel?
var itemID: String?
func convert(params: Dictionary<String, String>, queryParams: Dictionary<String, String>) {
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)
}
}
}
当基本模型填充或用户进行了一些更改时,前一个 View Controller 应该知道,并相应地进行更新。只需添加一个如 onModelUpdate()
的属性,当模型更新时调用此函数(如果它不为 nil)。
路由设计
URL 模式存储在一个类似树的基数中,它将首先将传入的 URL 分割成部分,然后逐个通过树进行匹配。
技巧
- 为了保持简单,URL 模式仅匹配到
String
。《code>app://profile/{id} 将在convert
方法中将params["id"]
作为String
获取。 - 可以将导航器注入到
Handler
的子协议中,以便更容易地进行导航。 SomeHandler
可以用作配置处理器,当通过 URL 如?debugcode=xxx
打开时,启用调试模式。
联系
在 Twitter 上关注并联系我。如果发现问题,请创建工单。拉取请求也非常欢迎。
许可协议
Elf 采用 MIT 许可协议发布。有关详细信息,请参阅 LICENSE 文件。