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 ... 
随机推荐
- 关于在生命周期当中进行setState操作的问题
			当需要监听组件的属性改变的时候有两个生命周期componentWillReceiveProps和componentWillUpdate 当使用componentWillUpdate的时候可以获取到将要 ... 
- POJ3170  Bzoj1671 [Usaco2005 Dec]Knights of Ni 骑士
			1671: [Usaco2005 Dec]Knights of Ni 骑士 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 281 Solved: 180 ... 
- android基本控件学习-----ToggleButton&Switch
			ToggleButton(开关按钮)和Switch(开关)讲解: 一.核心属性讲解: (1)ToggleButton textOn:按钮被选中的时候文字显示 textOff:按钮没有被选中的时候文字显 ... 
- MSP430G2553头文件解析
			MSP430寄存器中文注释---P1/2口(带中断功能) /************************************************************ ... 
- python的上下文管理
			说道上下文管理首先想到的就是这个: class MyResource: def __enter__(self): print("查询开始") return self def __e ... 
- 只用一次循环开销 将类似 1 A 、1 B 的数据返回成为 1 A,B 的拼接形式
			/// <summary> ///将类似 1 A .1 B 的数据返回成为 1 A,B 的拼接形式 /// </summary> /// <param name=&quo ... 
- Codeforces 最大流 费用流
			这套题目做完后,一定要反复的看! 代码经常出现的几个问题: 本机测试超时: 1.init函数忘记写. 2.addedge函数写成add函数. 3.边连错了. 代码TLE: 1.前向星边数组开小. 2. ... 
- Mysql varchar长度问题
			http://dinglin.iteye.com/blog/914276 http://www.cnblogs.com/fakis/archive/2011/03/07/1976532.html ... 
- Oracle 索引(转)
			一.索引介绍 1.1 索引的创建语法: CREATE UNIUQE | BITMAP INDEX <schema>.<index_name> ON <schema> ... 
- Python环境安装与配置
			1.官网下载:https://www.python.org/选择不同的版本 2.进入运行:使用pip安装selenium 3.设置pip的环境变量 4.安装后使用pip(一个Python包管理工具)安 ... 
