URL Handle in Swift (二) — 响应链处理 URL
最后更新: Swift4时候的博客,以前在 CMD markdown 上编辑的,现在搬到这里
更新日期: 2018-06-06
在上篇文章-URL Handle in Swift (一) -- URL 分解中,我们已经将URL进行了分解, 信息全部保存在了IGInstruction
类型之中. 在这篇文章之后, 我们将讨论如何构建一个类似iOS响应者链来处理IGInstruction
。
一、响应者链
iOS响应者链相关的知识在网络上一大把。 这里我就简单的说明一下。 UIApplication
、UIView
、UIViewController
继承于 UIResponder
, UIResponder
中有一个 next
, 表示在响应者链上的下一个响应者。
UIApplication.next
为nil
UIWindow.next
为UIApplication
,UIView.next
为SuperView
或者UIViewController
;UIViewController.next
情况就比较的复杂了:
UIWindow.rootViewController.next 为 UIWindow`;
通过
present(, animated:, completion:)
出来的VC
,next
为presentedViewController
;通过
navigationController?.pushViewController(, animated:)
出来的 出来的VC
,next
为navigationController
;UITabbarController
管理的viewControllers
,next
为UITabbarController
;UIPageViewController
管理的viewControllers
,next
为UIPageViewController
;
在处理 URL 过程中, 我们也仅仅需要考虑找到合适的 Responder, 然后执行响应的操作。实际上, 我们还可以简化一点, 因为在实际的开发中, 当接收到一个 URL, 最常见的就是弹出一个对应的控制器来进行操作。
二、寻找合适 Responder
首先定义一个 IGNode
协议,
import Foundation
public enum IGHandlerAction {
case ignoring
case handling(()->Void)
}
protocol IGHandlerable {
func handler(forIns instruction: IGInstruction) -> IGHandlerAction
}
extension IGHandlerAction {
@discardableResult
public func handle() -> Bool {
switch self {
case .handling(let handler):
handler()
default:
break
}
return self.isHandling
}
public var isHandling: Bool {
switch self {
case .handling(_):
return true
case .ignoring:
return false
}
}
public var hasAction: Bool {
switch self {
case .handling(_):
return true
default:
return false
}
}
}
protocol IGNode {
var igHanderable: IGHandlerable? { get }
var firstIGNode: IGNode { get }
var nextIGNode: IGNode? { get }
func handlerInChain(forIG instruction: IGInstruction, fromFirstNode: Bool) -> IGHandlerAction
}
extension IGNode where Self: UIResponder {
var nextIGNode: IGNode? {
var next = self.next
while next != nil {
if let node = next as? IGNode {
return node
}
next = next?.next
}
return nil
}
}
extension IGNode {
func handlerInChain(forIG instruction: IGInstruction, fromFirstNode: Bool) -> IGHandlerAction {
if fromFirstNode {
return self.firstIGNode.handlerInChain(forIG: instruction, fromFirstNode: false)
} else {
if let action = self.igHanderable?.handler(forIns: instruction), action.isHandling {
return action
} else {
return self.nextIGNode?.handlerInChain(forIG: instruction, fromFirstNode: false) ?? .ignoring
}
}
}
var firstIGNode: IGNode { return self }
}
UIViewController + IGNode
extension UIViewController: IGNode {
var igHanderable: IGHandlerable? {
return !self.ignoreIG ? (self as? IGHandlerable) : nil
}
@objc open var ignoreIG: Bool { return self.presentedViewController != nil }
var firstIGNode: IGNode {
if let presented = self.presentedViewController {
return presented.firstIGNode
} else {
return currentChildViewController?.firstIGNode ?? self
}
}
@objc open var currentChildViewController: UIViewController? {
return nil
}
}
extension UINavigationController {
@objc open override var currentChildViewController: UIViewController? {
return self.topViewController
}
}
extension UITabBarController {
@objc open override var currentChildViewController: UIViewController? {
return self.selectedViewController
}
}
extension UIPageViewController {
@objc open override var currentChildViewController: UIViewController? {
return self.viewControllers?.first ?? self
}
}
URL Handle in Swift (二) — 响应链处理 URL的更多相关文章
- URL Handle in Swift (一) -- URL 分解
更新时间: 2018-6-6 在程序开发过程之中, 我们总是希望模块化处理某一类相似的事情. 在 ezbuy 开发中, 我接触到了对于 URL 处理的优秀的代码, 学习.改进.记录下来.希望对你有所帮 ...
- thinkPHP四种URL访问方式(二)
原文:thinkPHP四种URL访问方式(二) 四.url的4种访问方式 1.PATHINFO 模式 -- (重点) http://域名/项目名/入口文件/模块名/方法名/键1/值1/键2/ ...
- iOS 获取当前响应链的First Responder (Swift)
import UIKit private weak var currentFirstResponder: AnyObject? extension UIResponder { static func ...
- iOS 响应链
一.UIResponder app 使用响应者对象接收和处理事件,只有继承 UIResponder 的类,才能处理事件. UIApplication.UIView.UIViewController 都 ...
- 追踪app崩溃率、事件响应链、Run Loop、线程和进程、数据表的优化、动画库、Restful架构、SDWebImage的原理
1.如何追踪app崩溃率,如何解决线上闪退 当 iOS设备上的App应用闪退时,操作系统会生成一个crash日志,保存在设备上.crash日志上有很多有用的信息,比如每个正在执行线程的完整堆栈 跟踪信 ...
- 事件分发&响应链
iOS的三种事件:触摸事件/运动事件/远程控制事件 typedef enum { UIEventTypeTouches, UIEventTypeMotion, UIEventTypeRemoteCon ...
- iOS-UIResponse之事件响应链及其事件传递
UIResponse之事件响应链及其事件传递 我们的App与用户进行交互,基本上是依赖于各种各样的事件.一个视图是一个事件响应者,可以处理点击等事件,而这些事件就是在UIResponder类中定义的. ...
- 设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型)
设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型) 1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就 ...
- iOS开发 - 事件传递响应链
序言 当我们在使用微信等工具,点击扫一扫,就能打开二维码扫描视图.在我们点击屏幕的时候,iphone OS获取到了用户进行了“单击”这一行为,操作系统把包含这些点击事件的信息包装成UITouch和UI ...
随机推荐
- 思维导图工具 & 原型设计工具
最近需要画出系统流程架构什么的,就用到了几个思维导图工具 1. XMind -- 思维导图工具 2. MindManager -- 思维导图工具 3. AXURE RP --原型设计工具
- java网络编程(二)
客户端程序: package net; import java.io.OutputStream; import java.net.Socket; /** * Created by hu on 2015 ...
- JQuery操作基本选择器
<body> <input type="button" id="btn1" value="选择为one的元素"/> ...
- AC日记——第K大的数 51nod 1105
1105 第K大的数 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注 数组A和数组B,里面都有n个整数.数组C共有n^2个整数,分别是A[0] * ...
- JMeter 中Random 随机函数的使用
场景:在做接口测试时,比如说要求用户的手机号码不允许重复,那此时可以通过Random 随机函数来解决此问题: 1.在JMeter 工具中,选择{选项-函数助手对话框-} 函数助手中选择 Random ...
- Java 8 Lambda表达式的使用
lambda表达式允许你通过表达式来代替功能接口.lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块). Lambda表达式还增 ...
- 2016集训测试赛(二十一)Problem C: 虫子
题目大意 给你一棵树, 每个点有一个点权. 有两种操作: link / cut 修改某个点的点权 每次操作后, 你要输出以下答案: 在整棵树中任意选两个点, 这两个点的LCA的期望权值. Soluti ...
- 2016北京集训测试赛(十六)Problem A: 任务安排
Solution 这道题告诉我们, 不能看着数据范围来推测正解的时间复杂度. 事实证明, 只要常数足够小, \(5 \times 10^6\)也是可以跑\(O(n \log n)\)算法的!!! 这道 ...
- js 拦截全局 ajax 请求
你是否有过下面的需求:需要给所有ajax请求添加统一签名.需要统计某个接口被请求的次数.需要限制http请求的方法必须为get或post.需要分析别人网络协议等等,那么如何做?想想,如果能够拦截所有a ...
- json字符串调整
碰到比较长的json字符串,不知道哪里出错时,可以找一个正确的json字符串,慢慢把它调整到需要的形式,而不是去分析,字符串太长,一直看,效率太慢,容易看花眼.