当前位置: 首页 > news >正文

四川网站建设服务公司国有企业参股管理暂行办法

四川网站建设服务公司,国有企业参股管理暂行办法,品牌网上授权,怎样一个域名做两个网站iOS 事件的主要由#xff1a;响应连 和 传递链 构成。一般事件先通过传递链#xff0c;传递下去。响应链#xff0c;如果上层不能响应#xff0c;那么一层一层通过响应链找到能响应的UIResponse。 响应链#xff1a;由最基础的view向系统传递#xff0c;first view -响应连 和 传递链 构成。一般事件先通过传递链传递下去。响应链如果上层不能响应那么一层一层通过响应链找到能响应的UIResponse。 响应链由最基础的view向系统传递first view - super view - ... - view controller - window - Application - AppDelegate传递链有系统向最上层view传递Application - window - root view - sub view - ... - first view 一、谁来响应事件 —— 传递链 只有继承了UIResponser的对象才能够接受处理事件。UIResponse是响应对象的基类定义了处理各种事件的接口。在 UIKit 中我们使用响应者对象Responder接收和处理事件。一个响应者对象一般是 UIResponder 类的实例它常见的子类包括 UIViewUIViewController 和 UIApplication这意味着几乎所有我们日常使用的控件都是响应者如 UIButtonUILabel 等等。 在 UIResponder 及其子类中我们是通过有关触摸UITouch的方法来处理和传递事件UIEvent具体的方法如下 open func touchesBegan(_ touches: SetUITouch, with event: UIEvent?) open func touchesMoved(_ touches: SetUITouch, with event: UIEvent?) open func touchesEnded(_ touches: SetUITouch, with event: UIEvent?) open func touchesCancelled(_ touches: SetUITouch, with event: UIEvent?) UIResponder 还可以处理 UIPress、加速计、远程控制事件这里仅讨论触摸事件。 在 UITouch 内存储了大量触摸相关的数据当手指在屏幕上移动时所对应的 UITouch 数据也会更新例如 这个触摸是在哪个 window 或者哪个 view 内发生的当前触摸点的坐标是前一个触摸点的坐标是当前触摸事件的状态是 这些都存储在 UITouch 里面。另外需要注意的是在这四个方法的参数中传递的是 UITouch 类型的一个集合 (而不是一个 UITouch)这对应了两根及以上手指触摸同一个视图的情况。我们以UIView 来作为视图层级的主要组成元素便于理解。但不止 UIView 可以响应事件实际只要是 UIResponder 的子类都可以响应和传递事件。 当我们触摸了屏幕。此时所拥有的信息是触摸点的坐标但无法直接知道用户是想点哪个视图。需要一个策略来找到这个第一响应者UIKit 为我们提供了命中测试hit-testing来确定触摸事件的响应者这个策略具体是怎么运作的 命中测试 图中还有一些细节需要先说明 在 检查自身可否接收事件 中如果视图符合以下三个条件中的任一个都会无法接收事件 view.isUserInteractionEnabled falseview.alpha 0.01view.isHidden true检查坐标是否在自身内部 这个过程使用了 func point(inside point: CGPoint, with event: UIEvent?) - Bool 方法来判断坐标是否在自身内部该方法是可以被重写的。从后往前遍历子视图重复执行 指的是按照 FILO 的原则将其所有子视图按照「后添加的先遍历」的规则进行命中测试。该规则保证了系统会优先测试视图层级树中最后添加的视图如果视图之间有重叠该视图也是同级视图中展示最完整的视图即用户最可能想要点的那个视图。在 按顺序看看平级的兄弟视图 时若发现已经没有未检查过的视图了则应走向 诶没有子视图符合要求。 我们举个例子来解释这个流程在例子中我们从当前 UIViewController 的根视图开始执行这个流程。下图中灰色视图 A 可以看作是当前 UIViewController 的根视图右侧表示了各个视图的层级结构用户在屏幕上的触摸点是处并且这 5 个视图都可以正常的接收事件。⚠️并且注意D 比 B 更晚添加到 A 上。 具体的流程如下 首先对 A 进行命中测试显然是在 A 内部的按照流程接下来检查 A 是否有子视图。我们发现 A 有两个子视图那我们就需要按 FILO 原则遍历子视图先对 D 进行命中测试后对 B 进行命中测试。我们对 D 进行命中测试我们发现不在 D 的内部那就说明 D 及其子视图一定不是第一响应者。按顺序接下来对 B 进行命中测试我们发现在 B 的内部按照流程接下来检查 B 是否有子视图。我们发现 B 有一个子视图 C所以需要对 C 进行命中测试。显然不在 C 的内部这时我们得到的信息是触摸点在 B 的内部但不在 B 的任一子视图内。得到结论B 是第一响应者并且结束命中测试。整个命中测试的走向是这样的A✅ -- D❎ -- B✅ -- C❎ B 实际上这个流程就是 UIView 的一个方法func hitTest(_ point: CGPoint, with event: UIEvent?) - UIView?方法最后返回的 UIView? 即第一响应者这个方法代码还原应该是这样的 class HitTestExampleView: UIView {override func hitTest(_ point: CGPoint, with event: UIEvent?) - UIView? {if !isUserInteractionEnabled || isHidden || alpha 0.01 {return nil // 此处指视图无法接受事件}if self.point(inside: point, with: event) { // 判断触摸点是否在自身内部for subview in subviews.reversed() { // 按 FILO 遍历子视图let convertedPoint subview.convert(point, from: self)//这句是判断触摸点是否在子视图内部在就返回视图不在就返回nillet resultView subview.hitTest(convertedPoint, with: event) if resultView ! nil { return resultView }}return self // 此处指该视图的所有子视图都不符合要求而触摸点又在该视图自身内部}return nil // 此处指触摸点是否不在该视图内部} } 小心越界 针对这个流程举个额外的例子如果按下图的视图层级和触摸点来判断的话最终获得第一响应者仍然是 B甚至整个命中测试的走向和之前是一样的A✅ -- D❎ -- B✅ -- C❎ B究其原因是在 D 检查触摸点是否在自身内部时答案是否所以不会去对 E 进行命中测试即使看起来我们点了 E。这个例子告诉我们要注意可点击的子视图是否会超出父视图的范围。另若有这种情况可以重写 func point(inside point: CGPoint, with event: UIEvent?) - Bool方法来扩大点击有效范围。对于这种处理方式个人觉得是可以但没必要寻求合理的视图布局和清晰易读的代码比这个关键。 二、怎样传递事件 —— 响应链 确定响应链成员 在找到了第一响应者之后整个响应链也随着确定下来了。所谓响应链是由响应者组成的一个链表链表的头是第一响应者链表的每个结点的下一个结点都是该结点的 next 属性。 其实响应链就是在命中测试中走通的路径。用上个章节的例子整个命中测试的走向是A✅ -- D❎ -- B✅ -- C❎我们把没走通的❎的去掉以第一响应者 B 作为头依次连接响应链就是B - A。实际上 A 后面还有控制器等但在该例子中没有展示控制器等所以就写到 A 默认来说若该结点是 UIView 类型的话这个 next 属性是该结点的父视图。但也有几个例外 如果是 UIViewController 的根视图则下一个响应者是 UIViewController。如果是 UIViewController 如果 UIViewController 的视图是 UIWindow 的根视图则下一个响应者是 UIWindow 对象。如果 UIViewController 是由另一个 UIViewController 呈现的则下一个响应者是第二个 UIViewController。UIWindow的下一个响应者是 UIApplication。UIApplication 的下一个响应者是 app delegate。但仅当该 app delegate 是 UIResponder 的实例且不是 UIView、UIViewController 或 app 对象本身时才是下一个响应者。 下面举个例子来说明。如下图所示触摸点是那根据命中测试B 就成为了第一响应者。由于 C 是 B 的父视图、A 是 C 的父视图、同时 A 是 Controller 的根视图那么按照规则响应链就是这样的 视图 B - 视图 C - 根视图 A - UIViewController 对象 - UIWindow 对象 - UIApplication 对象 - App Delegate 图中浅灰色的箭头是指将 UIView 直接添加到 UIWindow 上情况 沿响应链传递事件 触摸事件首先将会由第一响应者响应触发其 open func touchesBegan(_ touches: SetUITouch, with event: UIEvent?) 等方法根据触摸的方式不同如拖动双指具体的方法和过程也不一样。若第一响应者在这个方法中不处理这个事件则会传递给响应链中的下一个响应者触发该方法处理若下一个也不处理则以此类推传递下去。若到最后还没有人响应则会被丢弃比如一个误触。 我们可以创建一个 UIView 的子类并加入一些打印函数来观察响应链具体的工作流程。 class TouchesExampleView: UIView {override func touchesBegan(_ touches: SetUITouch, with event: UIEvent?) {print(Touches Began on colorBlock)super.touchesBegan(touches, with: event)}override func touchesMoved(_ touches: SetUITouch, with event: UIEvent?) {print(Touches Moved on colorBlock)super.touchesMoved(touches, with: event)}override func touchesEnded(_ touches: SetUITouch, with event: UIEvent?) {print(Touches Ended on colorBlock)super.touchesEnded(touches, with: event)} } 下面我们举一个例子。如下图A B C 都是 UIView我们将手指按照的位置和箭头的方向在屏幕上移动一段距离然后松开手。我们应该能在控制台看到下右图的输出。我们可以看到A B C 三个视图都积极的响应了每一次事件每次触摸的发生后都会先触发 B 的响应方法然后传递给 C在传递给 A。但是这种「积极」的响应其实意味着在我们这个例子中A B C 都不是这个触摸事件的合适接受者。他们之所以「积极」的将事件传递下去是因为他们查看了这个事件的信息之后认为自己并不是这个事件的合适处理者。当然了我们这边放的是三个 UIView他们本身确实也不应该能处理事件 那么如果我们把上图中的 C 换成平时使用的 UIControl 类控制台又会怎么打印呢如右下图所示会发现响应链的事件传递到 C 处就停止了也就是 A 的 touches 方法没有被触发。这意味着在响应链中UIControl 及其子类默认来说是不会将事件传递下去的。在代码中可以理解为 UIView 默认会在其 touches 方法中去调用其 next 的 touches 方法而 UIControl 默认不会去调用。这样就做到了当某个控件接受了事件之后事件的传递就会终止。另外UIScrollView 也是这样的工作机制。 UIControl 接收信息的机制是 target-action 机制和 UIGestureRecognizer 的处理方式相关但不完全相同 总结 总的来说触摸屏幕后事件的传递可以分为以下几个步骤 通过「命中测试」来找到「第一响应者」由「第一响应者」来确定「响应链」将事件沿「响应链」传递事件被某个响应者接收或没有响应者接收从而被丢弃 注这些步骤都是建立在不使用 UIGestureRecognizer 的基础上的 三、当手势识别参与响应链 下图为手势识别处理的流程图 更详细的流程 从图中我们可以看到在通过命中测试找到第一响应者之后会将 UITouch 分发给 UIResponder的touches 系列方法具体方法见上篇文章同时也会分发给手势识别系统让这两个处理系统同时工作。 首先要注意的是上图中蓝色部分的流程并不会只执行一次举例来说当我们用一根手指在一个视图上缓慢滑动时会产生一个 UITouch对象这个 UITouch 对象会随着你手指的滑动不断的更新自身同时也不断地触发 touches 系列方法。一般来说我们会得到如下类似的触发顺序 touchesBegan // 手指触摸屏幕 touchesMoved // 手指在屏幕上移动 touchesMoved // ... ... touchesMoved // ... touchesMoved // 手指在屏幕上移动 touchesEnded // 手指离开屏幕 UITouch 的 gestureRecognizers 属性中的存储了在寻找第一响应者的过程中收集到的手势而在不断触发touches 系列方法的过程中手势识别系统也在在不停的判断当前这个 UITouch 是否符合收集到的某个手势。 当手势识别成功 被触摸的那个视图也就是第一响应者会收到touchesCancelled的消息并且该视图不会再收到来自该 UITouch 的 touches 事件。同时也让该 UITouch 关联的其他手势也收到touchesCancelled并且之后不再收到此 UITouch 的 touches事件。这样做就实现了该识别到的手势能够独占该 UITouch。具体表现参考如下 touchesBegan // 手指触摸屏幕 touchesMoved // 手指在屏幕上移动 touchesMoved // ... ... touchesMoved // ... touchesMoved // 手指在屏幕上移动 touchesCancelled // 手势识别成功touches 系列方法被阻断 // 现在手指并没有离开屏幕 // 但如果继续滑动的话 // 并不会触发 touches 系列方法 当手势识别未成功 指暂时未识别出来不代表以后不会识别成功不会阻断响应链。注意这里指的是未成功并不一定是失败。在手势的内部状态中手势大部分情况下状态是 .possible指的是UITouch 暂时与其不匹配但之后可能有机会识别成功。而.fail是真的识别失败指的是以目前的触摸情况来看已经不可能是这个手势了并且在下个runloop 会从 gestureRecognizers中移除该手势。 举个例子 下面举个简单的例子模拟一下响应链和手势的相互影响。现在用一根手指在一个视图上触摸并滑动一段距离。下图给出了视图不带手势的情况和带一个 UIPanGestureRecognizer 手势的情况。 从图中我们可以看到当不带手势的情况下手指按下去的时候响应者的 touchBegan 方法会触发随着手指的移动touchMoved会不断触发当手指结束移动并抬起来的时候touchEnded 会触发。在这个过程中我们接收到一直是一个不断更新的 UITouch。 在该视图有添加一个 UIPanGestureRecognizer 手势的情况下我们多了下方这一条来表示与响应链同时工作的手势识别系统可以看到手势识别系统也是在手指按下去那一刻就开始工作的前半段处于一直正在识别的状态。在我们拖动了很小一段距离之后注意这时候我们的手指还没抬起 手势识别系统确定了该UITouch所做的动作是符合 UIPanGestureRecognizer 的特点的于是给该视图的响应链发送了touchCancelled 的信息从而阻止这个UITouch继续触发这个视图的 touches 系列方法同时也取消了别的相关手势的 touches系列方法图中未体现。在这之后被调用的只有与手势关联的target-action 方法也就是图中的墨绿色节点 call PanFunction。 再进一步理解 为了图片的美观和易读在图片中我隐去了不少细节在此列出 1、手势识别器的状态在图中未标出 手势在图中 recognizing 的橙色节点处和 recognized棕色节点处都处于.possible状态手势在图中绿色节点处的状态变化是.began - [.changed] - ended 2、手势识别器不是响应者但也有touches 系列方法比它所添加的视图的 touches方法更早那么一点触发 从图中也可以看出手势那条线上的每个节点都稍靠左一些手势那条线上的橙、棕、墨绿色节点处也可以看做手势识别器的 touches 方法触发 3、更详细的触发顺序应当如下图所示在一个 UIView 上添加了 UIPanGestureRecognizer 并单指在上面滑动一段距离的情况 手势和响应者的 touches 方法名字是一样的都是「began」「moved」「ended」「cancelled」。很容易和手势识别器的 state属性搞混state属性是根据每个手势的类型离散型/连续型的不同可能有 .possible、.began、.changed、.ended、.cancelled、.failed 这些状态名字很像方法名很像但不是一回事。 我们可以通过配置手势的属性来改变它的表现下面介绍三个常用的属性 1、cancelsTouchesInView该属性默认是 true。顾名思义如果设置成false当手势识别成功时将不会发送touchesCancelled给目标视图从而也不会打断视图本身方法的触发最后的结果是手势和本身方法同时触发。有的时候我们不希望手势覆盖掉视图本身的方法就可以更改这个属性来达到效果。 2、delaysTouchesBegan该属性默认是 false。在上个例子中我们得知在手指触摸屏幕之后手势处于 .possible 状态时视图的 touches 方法已经开始触发了当手势识别成功之后才会取消视图的 touches 方法。当该属性时 true 时视图的touches 方法会被延迟到手势识别成功或者失败之后才开始。也就是说假如设置该属性为 true 在整个过程中识别手势又是成功的话视图的touches 系列方法将不会被触发。 3、delaysTouchesEnded该属性默认是 true。与上个属性类似该属性为true时视图的touchesEnded将会延迟大约 0.15s 触发。该属性常用于连击比如我们需要触发一个双击手势当我们手指离开屏幕时应当触发touchesEnded如果这时该属性为 false那就不会延迟视图的 touchesEnded方法将会立马触发 那我们的双击就会被识别为两次单击。当该属性是 true 时会延迟 touchesEnded 的触发将两次单击连在一起来正常识别这种双击手势。 UIControl 与手势识别 由于 UIControl 接收 target-action 方法的方式是在其 touches 方法中识别、接收、处理而手势的 touches 方法一定比其所在视图的 touches 方法早触发。再根据上文的描述的触发规则可以得到的结论是对于自定义的 UIControl 来说手势识别的优先级比 UIControl 自身处理事件的优先级高。 举个例子来说当我们给一个 UIControl 添加了一个 .touchupInside 的方法又添加了一个 UITapGestureRecognizer 之后。点击这个 UIControl会看到与手势关联的方法触发了并且给 UIControl 发送了 touchCancelled导致其自身的处理时间机制被中断从而也没能触发那个 .touchupInside 的方法。 同时这样的机制可能会导致一个问题当我们给一个已经拥有点击手势的视图添加一个 UIControl 作为子视图那么我们无论怎么给该 UIControl 添加点击类型的 target-action 方法最后的结果都是触发其父视图的手势因为在命中测试的过程中收集到了这个手势并且中断 UIControl 的事件处理导致添加的 target-action 方法永远无法触发。 那其实已经给我们做了一个解决方案UIKit 对部分控件同时也是 UIControl 的子类做了特殊处理当这些控件的父视图上有与该控件冲突功能的手势时会优先触发控件自身的方法不会触发其父视图上的那个手势。具体的控件和冲突触发方式如下图 也举个例子来说当我们给一个已经拥有点击手势的视图添加一个 UIButton作为子视图并且给按钮添加点击类型的 target-action 方法那么当点击按钮时按钮的 target-action 方法会触发手势的方法会被忽略。 并且文档中也提到了如果不想要这种情况发生那就应当把手势添加到目标控件上因为手势比控件更早识别到事件也就是上文提到的给 UIControl添加了 .touchupInside 方法的例子这样的话生效的就是手势了。 总结 总的来说手势识别器在大多数情况下识别屏幕触摸事件的优先级比控件本身的方法的优先级高。 所以在开发的过程中注意不要让手势覆盖控件本身的方法实现。同时也要理解默认情况下手势识别在一开始实际上并不会阻止控件自身的 touches 系列方法而是在之后的某个时机去取消。另外在 UIKit 中也对部分情况做了特殊处理让 UIKit 控件有机会跳过父视图的手势识别去获得事件的控制权。
http://www.dnsts.com.cn/news/118869.html

相关文章:

  • 上海定制网站建设模板网婚纱
  • 小程序注册需要费用吗seo搜索引擎优化师
  • 软件下载网站如何建设.net 网站制作
  • 做网站推广弊端asp.net 获取网站的绝对路径
  • 广东高端网站建设网址转app制作生成器
  • 怀来住房和城乡建设局网站芜湖代理公司注册
  • 紫搜科技建站注册企业的流程有哪些
  • 网站建设咋打开自己网站主页网址深圳教育平台网站建设
  • 乐从网站制作如何编写网站建设销售的心得
  • 国内优秀公司网站网站死链接怎么处理
  • 家具网站首页设计wordpress 主页排序
  • 成都哪里有网站开发公司模板外贸网站建设
  • 中国建设银行网站分期通网站开发对显卡的要求
  • 网站制作 合同网站制作和如何推广
  • 郑州专业做网站的制作网络游戏
  • 电竞网站建设方案建网站资料
  • 衡水做外贸网站win7系统可以做网站吗
  • 福州市做公司网站哪家好网易公司邮箱
  • 西安php网站开发培训班wordpress搭建discuz
  • 学生做网站教程金融互助网站建设
  • php做网站登陆验证下载58同城网招聘找工作
  • 个人游戏网站备案河北省住房和城乡建设部网站
  • 网站制作毕业设计本地的南通网站建设
  • 360网站提交网页设计总结报告500字
  • 知名网站服务器wordpress字体更改
  • 2017年网站推广怎么做2024年小微企业100至300万
  • 向网站上传文件怎么做seo和sem的区别是什么
  • 宛城区微网站开发wordpress登陆函数
  • python 做的网站有哪些辽宁省网站制作公司排名
  • iis6cgi php网站缓存asp.net 价格查询网站