Elf 0.5.1

Elf 0.5.1

limboy维护。



Elf 0.5.1

Elf

Swift Cocoapods

Elf是一个轻量级的纯Swift路由,用于处理URL。使传入的URL能够找到正确的处理器。这就是Elf所做的一切。

Elf Workflow

那么处理器是什么意思呢?

protocol Handler: class {
    func convert(params:Dictionary<String, String>, queryParams: Dictionary<String, String>)
    func handle()
}

如果Elf找到了正确的处理器,它将会先调用convert方法,传入paramsqueryParams。在这个方法中,这些参数可以被转换为内部属性。

接下来将调用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 文件。