class ViewController:UIViewController { override func viewDidLoad() { super.viewDidLoad() } override func touchesBegan(_ touches:Set<UITouch>,with event:UIEvent?) { print(“touchesBegan”); } override func touchesMoved(_ touches:Set<UITouch>, with event:UIEvent?) { print(“touchesMoved”); } override func touchesEnded(_ touches:Set<UITouch>,with event:UIEvent?){ print(“touchesEnded”); } override func touchesCancelled(_ touches:Set<UITouch>, with event:UIEvent?) { print(“touchesCancelled”); } }
override func touchesMoved(_ touches:Set<UITouch>, with event:UIEvent?) { //需要先判断是否触屏区域是否在图像内,省略 if!isTouchInImageView{ return; } let touch = touches.first let touchPoint = touch?.location(in:self.view) let touchPrePoint = touch?.previousLocation(in:self.view) let disX = (touchPoint?.x)!- (touchPrePoint?.x)! let disY = (touchPoint?.y)!- (touchPrePoint?.y)! var centerPoint = self.imageView.center centerPoint.x += disX centerPoint.y += disY self.imageView.center = centerPoint }
10 override func touchesBegan(_ touches:Set<UITouch>, with event:UIEvent?) { 11 let touch = touches.first 12 let touchPoint = touch?.location(in:self.view) 13 14 let imageViewFrame = self.imageView.frame 15 let minX = imageViewFrame.origin.x 16 let
对于触摸事件UIResponder内部提供了以下方法来处理事件: 事件对象在UIEvent UIEvent.h文件中,我们可以看到有一个UIEventType类型的属性,这个属性表示了当前的响应事件类型 每次点击发生的时候,点击对象都放在一个集合中传入UIResponder的回调方法中,我们通过集合中对象获取用户点击的位置。 UIResponder是所有响应者对象的基类,它不仅为事件处理,而且也为常见的响应者行为定义编程接口。 UIApplication、UIView、和所有从UIView派生出来的UIKit类(包括UIWindow)都直接或间接地继承自UIResponder类。 跟UIResponder相关其他值得注意的地方 UIApplication对象和每个UIWindow对象都在sendEvent:方法(两个类都声明了这个方法)中派发事件。
对象交互方式,简而言之,就是 通过在 UIResponder上挂一个 category,使得事件和参数可以沿着 responder chain 逐步传递。 对于那种 subviews 特别多,事件又需要层层传递的层级视图特别好用,但是,缺点也很明显,必须依赖于 UIResponder 对象。 然后UIResponder对象有一个重要的属性叫做nextResponder, 下一个响应者,可以保证找到当前view的事件的接收者 可以建立一个 UIResponder的类别,在类别中扩建一个方法, 在需要处理的地方重写 UIResponder的类别中的这个方法即可使整个传递终结掉。大大优化了整个事件处理过程。 由上至下的事件传递实现方法 #import "UIResponder+Router.h" @implementation UIResponder (Router) - (void)routerWithEventName
UIView的继承结构为:UIResponder:NSObject。可以看出UIView的直接父类为UIResponder类。 可见UIResponder是用来响应事件的,也就是说UIView可以响应用户事件。 2.CALayer的继承结构:NSObject 直接从NSObject继承,因为缺少了UIResponder类,所以CALayer不能响应任何的用户事件。
一、事件 iOS里有三种事件:触摸(touch)、加速(motion)、远程控制 在UIResponder里,有以下事件处理 // 触摸事件 - (void)touchesBegan:(NSSet withEvent:(UIEvent *)event; // 远程控制事件 - (void)remoteControlReceivedWithEvent:(UIEvent *)event; 二、寻找响应者(UIResponder )-事件传递 响应者:继承UIResponder的对象称之为响应者对象,能够处理touchesBegan等触摸事件 当一个Touch事件产生时,要先找到响应者,iOS通过Hit-Test机制来寻找响应者 ,每一个UIView(继承自UIResponder)都有以下的方法 - (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent 四、实例分析 UIButton的继承链是: UIButton->UIControl->UIView->UIResponder->NSObject UIApplication能够接受事件,因为UIApplication
简述 本文将讲述在iOS开发中如何根据某个UIView来获取所属的UIViewController UIResponder 在iOS中UIResponder类是专门用来响应用户的操作处理各种事件的,包括触摸事件 我们知道UIApplication、UIView、UIViewController这几个类是直接继承自UIResponder,所以这些类都可以响应事件。 返回第一个找到视图控制器 UIResponder *responder = view; while ((responder = [responder nextResponder])){
先说一下iOS系统的事件传递,它是通过UIResponder从上往下传递的,UIWindow, UIViewController, UIView等都是继承自UIResponder的,所以它们都可以响应事件 实现方式 给UIResponder添加一个分类 .h文件 #import <UIKit/UIKit.h> @interface UIResponder (Router) - (void)routerEventWithName :(NSString *)eventName userInfo:(NSDictionary *)userInfo; @end .m文件 #import "UIResponder+Router.h" @implementation UIResponder (Router) - (void)routerEventWithName:(NSString *)eventName userInfo:(NSDictionary
CALayer:http://blog.csdn.net/ZY_FlyWay/article/details/59039800 我们从苹果官方文档可以知道: UIView 继承于 UIResponder (UIResponder继承于NSObject) CALayer继承于 NSObject 所以他们之间的差异来自于UIResponder定义的那一部分。 1、UIResponder是干嘛的呢? 答:看完这一个就懂了 一句话UIVIew可以响应事件,而Layer不可以。 2、UIView和CALayer有什么关系呢。
继承结构 UIView的继承结构为: UIResponder : NSObject。 UIResponder是用来响应事件的,也就是UIView可以响应用户事件 CALayer的继承结构为: NSObject 直接从 NSObject继承,因为缺少了UIResponder类,所以CALayer UIView是视图的基类,UIViewController是视图控制器的基类,UIResponder是表示一个可以在屏幕上响应触摸事件的对象; 所属框架 UIView是在 /System/Library /Frameworks/UIKit.framework中定义的 UIKit主要是用来构建用户界面,并且是可以响应事件的(源于UIView的父类UIResponder) UIView是用来显示内容的,可以处理用户事件
通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目 通过runtime对给crash方法一个默认的实现 static BOOL (*originalImpl)(id, SEL, UIResponder *, UIResponder*, UIEvent* ) = nil; - (BOOL)_wantsForwardingFromResponder:(UIResponder *)arg1 toNextResponder :(UIResponder *)arg2 withEvent:(UIEvent *)arg3 { NSString* responderClassName = NSStringFromClass ObjcSeeker seekInstanceNextOirignalImpl:self selector:_cmd]; originalImpl = (BOOL (*)(id, SEL, UIResponder *, UIResponder*, UIEvent* ))impl; } if (originalImpl !
UIView @interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UIFocusItemContainer, CALayerDelegate> @property(nonatomic,readonly,strong) CALayer *layer; @end @interface UIResponder : NSObject <UIResponderStandardEditActions> 继承自UIResponder,间接继承自NSObject,主要是用来构建用户界面的,并且可以响应事件。
接下来从这三个概念UIEvent,UIResponder、Hit-Testing、Responder Chain入手,为你详细讲解这句话的含义。 UIResponder UIResponder 类提供了一组接口专门用来响应用户的操作,处理各种事件,其中包括触摸事件(Touch Events)、运动事件(Motion Events)、远程控制事件( 在UIKit中,UIApplication、UIView、UIViewController这几个类都是直接继承自UIResponder类 第一响应者(first responder) 第一响应者能够优先处理事件 CGRectContainsPoint(hitFrame, point); } @end Responder Chain Responder Chain 暂且翻译为“响应链”,它是由一些列的响应者(UIResponder 更多应用解决方案,请参考http://zhoon.github.io/ios/2015/04/12/ios-event.html 参考文献 UIResponder Class Reference UIResponder
UIApplicationMain(argc, argv, nil, appDelegateClassName);} main.cpp相关代码: truct AppDelegate_IMPL { struct UIResponder_IMPL UIResponder_IVARS;};/* @end */ int main(int argc, char * argv[]) { NSString * appDelegateClassName UIApplicationMain(argc, argv, nil, appDelegateClassName);} 2、clang编译后: struct AppDelegate_IMPL { struct UIResponder_IMPL UIResponder_IVARS;}; int main(int argc, char * argv[]) { NSString * appDelegateClassName; /* @
UIApplicationMain(argc, argv, nil, appDelegateClassName); } main.cpp相关代码: struct AppDelegate_IMPL { struct UIResponder_IMPL UIResponder_IVARS; }; /* @end */ int main(int argc, char * argv[]) { NSString * appDelegateClassName UIApplicationMain(argc, argv, nil, appDelegateClassName); } 2、clang编译后: struct AppDelegate_IMPL { struct UIResponder_IMPL UIResponder_IVARS; }; int main(int argc, char * argv[]) { NSString * appDelegateClassName;
iOS中很多类型的事件分发,都依赖于响应链;在响应链中,所有对象的基类都是UIResponder,也就是说所有能响应事件的类都是UIResponder的子类,UIApplication/ UIView/ UIViewController都是UIResponder的子类,这说明所有的Views,绝大部分Controllers(不用来管理View的Controller除外)都可以响应事件。 PS:CALayer不是UIResponder的子类,这说明CALayer无法响应事件,这也是UIView和CALayer的重要区别之一。 在UIResponder中,提供以下几个方法,几个方法分别表示点击的不同状态,大家看名字就能明白差不多: - (void)touchesBegan:(NSSet *)touches withEvent 这里就说到了另一个问题,UIResponder在知道需要处理事件的时候,还是有决定权的,比如我可以决定让整个响应链继续走下去,或者直接中断掉整个响应链。
Responder Chain: I 响应者对象 在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件,我们称之为“响应者对象”。 1.1 触摸事件 UIApplication、UIViewController、UIView都继承于UIResponder。 UIResponder内部提供了以下方法来处理事件 //一根或者多根手指开始触摸view,系统会自动调用view的下面方法 - (void)touchesBegan:(NSSet<UITouch *> iOS中的响应者链(Responder Chain)是用于确定事件响应者的一种机制,其中的事件主要指触摸事件(Touch Event),该机制和UIKit中的UIResponder类紧密相关。 响应触摸事件的都是屏幕上的界面元素,而且必须是继承自UIResponder类的界面类(包括各种常见的视图类及其视图控制器类,如UIView和UIViewController)才可以响应触摸事件。
iOS 中的事件响应者主要分为两类,分别为UIResponder及UIGestureRecognizer,其中UIControl是一种比较特殊的UIResponder,所以本文将事件响应者分为以下三种类型进行讨论 UIResponder 每个响应者都是一个 UIResponder 对象,即所有派生自 UIResponder 的对象,本身都具备响应事件的能力。 优先级 当我们在一个添加了手势的UIResponder上执行非连续的双击操作,触发的回调消息如下表所示。 UIControl 事件通知方式 UIControl作为UIResponder的派生类,其也具有UIResponder 的touch系列四个方法,但其内部对这四个方法进行了重写,在 touchBegin 它与普通的UIResponder有何不同呢?我们先看一下 Apple 官方的一些介绍。
在各个大类型中再细化区分 @property(nonatomic, readonly, nullable) NSSet <UITouch *> *allTouches; // 当前事件触发时的所有UITouch对象 2 UIResponder 事件响应者(UIResponder)的查找与事件的响应: 响应者(responder)的概念:在iOS系统中,响应者是指能响应并处理事件的对象,UIResponder是所有responder对象的基类 UIApplication / UIViewController / UIView 以及所有继承UIView的UIKit类(包含UIWindow)都直接或间接的继承了UIResponder,这就意味着所有的