最后更新: Swift4时候的博客,以前在 CMD markdown 上编辑的,现在搬到这里

更新日期: 2018-06-06

上篇文章-URL Handle in Swift (一) -- URL 分解中,我们已经将URL进行了分解, 信息全部保存在了IGInstruction类型之中. 在这篇文章之后, 我们将讨论如何构建一个类似iOS响应者链来处理IGInstruction

一、响应者链

iOS响应者链相关的知识在网络上一大把。 这里我就简单的说明一下。 UIApplicationUIViewUIViewController 继承于 UIResponder, UIResponder中有一个 next, 表示在响应者链上的下一个响应者。

  1. UIApplication.nextnil

  2. UIWindow.nextUIApplication, UIView.nextSuperView 或者 UIViewController;

  3. UIViewController.next 情况就比较的复杂了:

  • UIWindow.rootViewController.next 为 UIWindow`;

  • 通过 present(, animated:, completion:)出来的 VC, nextpresentedViewController;

  • 通过 navigationController?.pushViewController(, animated:)出来的 出来的 VC, nextnavigationController;

  • UITabbarController管理的 viewControllers, nextUITabbarController;

  • UIPageViewController管理的 viewControllers, nextUIPageViewController;

在处理 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的更多相关文章

  1. URL Handle in Swift (一) -- URL 分解

    更新时间: 2018-6-6 在程序开发过程之中, 我们总是希望模块化处理某一类相似的事情. 在 ezbuy 开发中, 我接触到了对于 URL 处理的优秀的代码, 学习.改进.记录下来.希望对你有所帮 ...

  2. thinkPHP四种URL访问方式(二)

    原文:thinkPHP四种URL访问方式(二) 四.url的4种访问方式      1.PATHINFO 模式 -- (重点) http://域名/项目名/入口文件/模块名/方法名/键1/值1/键2/ ...

  3. iOS 获取当前响应链的First Responder (Swift)

    import UIKit private weak var currentFirstResponder: AnyObject? extension UIResponder { static func ...

  4. iOS 响应链

    一.UIResponder app 使用响应者对象接收和处理事件,只有继承 UIResponder 的类,才能处理事件. UIApplication.UIView.UIViewController 都 ...

  5. 追踪app崩溃率、事件响应链、Run Loop、线程和进程、数据表的优化、动画库、Restful架构、SDWebImage的原理

    1.如何追踪app崩溃率,如何解决线上闪退 当 iOS设备上的App应用闪退时,操作系统会生成一个crash日志,保存在设备上.crash日志上有很多有用的信息,比如每个正在执行线程的完整堆栈 跟踪信 ...

  6. 事件分发&响应链

    iOS的三种事件:触摸事件/运动事件/远程控制事件 typedef enum { UIEventTypeTouches, UIEventTypeMotion, UIEventTypeRemoteCon ...

  7. iOS-UIResponse之事件响应链及其事件传递

    UIResponse之事件响应链及其事件传递 我们的App与用户进行交互,基本上是依赖于各种各样的事件.一个视图是一个事件响应者,可以处理点击等事件,而这些事件就是在UIResponder类中定义的. ...

  8. 设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型)

     设计模式(十二)职责链模式(Chain of Responsibility)(对象行为型) 1.概述 你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就 ...

  9. iOS开发 - 事件传递响应链

    序言 当我们在使用微信等工具,点击扫一扫,就能打开二维码扫描视图.在我们点击屏幕的时候,iphone OS获取到了用户进行了“单击”这一行为,操作系统把包含这些点击事件的信息包装成UITouch和UI ...

随机推荐

  1. LOJ#2083. 「NOI2016」优秀的拆分

    $n \leq 30000$的字符串,问其所有子串的所有AABB形式的拆分有多少种.$t \leq 10$组询问. $n^3$过80,$n^2$过95,鬼去写正解.. $n^2$:先枚举一次算每个位置 ...

  2. luogu 2463 [SDOI2008]Sandy的卡片 kmp || 后缀数组 n个串的最长公共子串

    题目链接 Description 给出\(n\)个序列.找出这\(n\)个序列的最长相同子串. 在这里,相同定义为:两个子串长度相同且一个串的全部元素加上一个数就会变成另一个串. 思路 参考:hzwe ...

  3. vue 设置头文件

    vue的头文件是在index.html文件中设置的,毕竟vue的入口 先说一下标签页的名字: 就是这个名字的设置,要想每个标签页的名字都不一样,需要做以下这三步:1. 首先,在index.html文件 ...

  4. hdu 5685(逆元)

    Problem A Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  5. 在Alfred添加自定义站内搜索

    1.Google的站内搜索和渣度的对比,懒得吐槽了 2.在Alfred添加自定义站内搜索步骤 Add Custome Search 把搜索某个关键词的url复制到里面,把url里的关键词替换成{que ...

  6. ios开发某个页面横不过来屏幕的时候

    某一个页面需要横屏,其他的页面任然保持竖屏需要以下关键的几个步骤: 1.修改系统代理方法的返回值 -(UIInterfaceOrientationMask)application:(UIApplica ...

  7. layui如何使用内部jQuery?

    遇到问题情境: 由于Layui部分内置模块依赖jQuery,所以没有单独引入jQuery,但是在使用$常规写法获取dom元素时,提示未定义 出现问题的原因: 由于Layui部分内置模块依赖jQuery ...

  8. Codeforces 371C Hamburgers (二分答案)

    题目链接 Hamburgers 二分答案,贪心判断即可. #include <bits/stdc++.h> using namespace std; #define REP(i,n) fo ...

  9. 最短Hamilton路径

    题目描述 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每 ...

  10. NOIP2016模拟赛三 Problem C: 不虚就是要AK

    题目大意 给定一棵带有边权的树, 问你在树上随机选两个点, 它们最短路径上的边权之和为\(4\)的倍数的概率为多少. Solution 树分治. 没什么好讲的. #include <cstdio ...