来自 电脑系统 2019-09-19 12:04 的文章
当前位置: 金沙澳门官网网址 > 电脑系统 > 正文

上学笔记

WMGCanvasControl 重假若使用 Target-Action 设计形式将触摸事件转变到控件事件。对于 UIControl 中 Target-Action 具体落到实处能够一直参谋:UIKit: UIControl 。

-(instancetype)initWithFrame:(CGRect)frametitle:(NSString*)titleimage:(UIImage*)image;

功效图如下:

}

1、WMGCanvasControl 未有消除数十次 addTarget 难题

依附代码测量检验和读书源码可见,多次调用 addTarget:action:forControlEvents: 方法,会成立四个 __WMGCanvasControlTargetAction 并加多到 _targetActions 中;这里会导致同一事件,对应的法门会被调用数十次。

此地应该做去重判定。

@interfaceImageControl:UIControl

私家感到 WMGCanvasControlUIControl 类应该相似,不推荐直接行使,应该作为父类提供通用的接口;可是为了演示成效以及断点调试,我们直接直接实例化WMGCanvasControlWMGCanvasControl 继承自 UIView 的,这里就直接参照他事他说加以考察实例 UIView 的方式:

其实在UIControl的文书档案中,addTarget:action:forControlEvents:方法的证实还或许有这么一句:

WMGCanvasControl *control = [[WMGCanvasControl alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];[control addTarget:self action:@selector(controlClick:) forControlEvents:UIControlEventTouchUpInside];control.backgroundColor = [UIColor redColor];[self.view addSubview:control]; //点击视图会调用下面方法- controlClick:(WMGCanvasControl *)control { NSLog(@"%s %@",__func__,control);}

-(void)viewDidLoad{

WMGCanvasControl 内部贯彻逻辑

控件是我们在开采中常用的视图工具,能很好的表述客商的意向。大家得以利用UIKit提供的控件,也得以自定义控件。当然,UIControl除了上述的局地方式,还应该有局地性质和方法,以及部分常量,大家能够参照文书档案。

2、对于可变数组的读写操作,应该要做二十八线程安全

那篇我们由此翻阅 WMGCanvasControl 源码可以大要知道,怎么着行使 Target-Action 来将触摸事件转变来控件事件;在达成的长河中,需求解析对象间的保有关系,在须求时用 weak 来打破循环援引。

自然,猛烈推荐看文末参谋文献,将 UIControl 讲的很透顶。

UIKit: UIControl

本例将会轻便地组成这两边。先来拜访效果:

从 Graver·学习笔记·入门使用 中能够领会:UIView 是继续自 UIResponder,进而有了响应触摸事件和散发事件的才能;不过,大家在应用 UIButton、UISlider、UIPageControl 等控件的时候,日常利用 addTarget:action:forControlEvents: 来拓宽事件绑定,这几个是因为它们的父类 UIControl 已经落实好:将触摸事件转化成控件事件,便于平常开垦使用。

[controladdTarget:selfaction:@selector(tapImageControl:)forControlEvents:UIControlEventTouchUpInside];

2、可变数组 _targetActions 管理对象的风云

动用可变数组来管理对象当前监听的风浪,_targetActions 里面是 __WMGCanvasControlTargetAction 对象。

@interface WMGCanvasControl (){ NSMutableArray * _targetActions;}// 为对象增减监听事件- addTarget:target action:action forControlEvents:(UIControlEvents)controlEvents{ if { __WMGCanvasControlTargetAction *t = [[__WMGCanvasControlTargetAction alloc] init]; t.target = target; t.action = action; t.controlEvents = controlEvents; [[self _targetActions] addObject:t]; }}

-(void)touchesCancelled:(NSSet<UITouch*>*)toucheswithEvent:(UIEvent*)event

1、weak 来化解 Target-Action 循环引用

此处用 UIKit: UIControl 中的图例来陈说为啥会产出循环援引,所以 __WMGCanvasControlTargetAction 中供给用 weak 来修饰 target,来打破循环援引。

金沙澳门官网网址 1image

-(BOOL)beginTrackingWithTouch:(UITouch*)touchwithEvent:(UIEvent*)event

金沙澳门官网网址 2image

实例:七个带Label的图片控件

3、利用 UIResponder 脾性将触摸事件转变来控件事件

由此重写 UIResponder 中的触摸事件的诀要,将分化触摸事件转形成对应的控件事件,利用 [[UIApplication sharedApplication] sendAction:action to:target from:self forEvent:event] 将事件传递给相应的目的。

//转换简化代码- touchesBegan:touches withEvent:(UIEvent *)event{ UIControlEvents currentEvents = UIControlEventTouchDown; [self _sendActionsForControlEvents:currentEvents withEvent:event];}- sendActionsForControlEvents:(UIControlEvents)controlEvents{ [self _sendActionsForControlEvents:controlEvents withEvent:nil];}- sendAction:action to:target forEvent:(UIEvent *)event{ [[UIApplication sharedApplication] sendAction:action to:target from:self forEvent:event];}

self.view.backgroundColor=[UIColorwhiteColor];

1、实现 __WMGCanvasControlTargetAction 私有类

__WMGCanvasControlTargetAction 私有类是用来代表三个 Target-Action 的:target 表示收到事件的靶子、action 表示事件触发的办法、control伊夫nts 表示哪一种事件。

@interface __WMGCanvasControlTargetAction : NSObject@property (nonatomic, weak) id target;@property (nonatomic, assign) SEL action;@property (nonatomic, assign) UIControlEvents controlEvents;@end

提供自定义的追踪行为。

同样,Graver 中 WMGCanvasControl 也兑现了 UIControl 相似地成效,这里大家共同来寻访哪些选择那几个类及其完毕细节。

小结

故此,UIControl内部实际上是有二个可变数组(_targetActions)来保存Target-Action,数组中的各种成分是三个UIControlTargetAction对象。UIControlTargetAction类是多少个私有类,我们得以在iOS-Runtime-Header中找到它的头文件:

// ImageControl.m

-(void).cxx_destruct;

出于大家重写了sendAction:to:forEvent:方法,所以最后处理事件的Selector是ImageControl的handleAction:方法,并非ViewController的tapImageControl:方法。

本文将经过二个自定义的UIControl子类来拜会UIControl的中坚使用格局。不过在开班以前,让大家先来领悟一下Target-Action机制。

示范工程的代码已上传到github,能够在这里下载。另外,推荐一下SVSegmentedControl本条控件,我们能够钻探下它的达成。

id_target;

// 将事件传递到对象自己来管理

@interfaceUIControlTargetAction:NSObject{

对此特定的轩然大波,大家需求观看或修改分发到target对象的行为新闻。

实则,咱们在程序有个别合适的岗位打个断点来观望UIControl的内部结构,能够看看那般的结果:

NSLog(@"handle Action");

-(BOOL)continueTrackingWithTouch:(UITouch*)touchwithEvent:(UIEvent*)event

再次回到大家的主旨来,大家将促成一个带Label的图形控件。常常意况下,我们会基于以下多个原因来贯彻贰个自定义的控件:

-(void)addTarget:(id)targetaction:(SEL)actionforControlEvents:(UIControlEvents)controlEvents

-(void)removeTarget:(id)targetaction:(SEL)actionforControlEvents:(UIControlEvents)controlEvents

BOOL_cancelled;

-(void)touchesMoved:金沙澳门官网网址 ,(NSSet<UITouch*>*)toucheswithEvent:(UIEvent*)event

假诺想博得控件对象具有相关的target对象,则足以调用allTargets方法,该方式再次回到一个会见。集结中恐怕包含NSNull对象,表示至少有叁个nil目的对象。

-(BOOL)cancelled;

在测量试验中,大家得以窥见当大家的触摸点沿着荧屏移出控件区域名,依然会一连追踪触摸操作,cancelTrackingWith伊夫nt:新闻未有被发送。为了判断当前触摸点是或不是在控件区域类,能够选取touchInside属性,那是个只读属性。不超过实际测的结果是,在控件区域广阔自然限制内,该值依旧会被标识为YES,即用于决断touchInside为YES的区域会比控件区域要大。

而一旦想赢得有些target对象及事件有关的有所action,则能够调用actionsForTarget:forControlEvent:方法。

=

除此以外,假诺大家以同一组target-action和event多次调用addTarget:action:forControl伊芙nts:方法,在_targetActions中并不会重复增加UIControlTargetAction对象。

别的,sendAction:to:for伊芙nt:实际上也被UIControl的另二个艺术所调用,即sendActionsForControl伊芙nts:。这几个办法的作用是发送与钦命项目相关的具有行为音信。大家能够在任性地点(富含控件内部和外界)调用控件的这些艺术来发送参数controlEvents钦赐的新闻。在大家的演示中,在ViewController.m中作了之类测量试验:

基础的布局我们在此不切磋。大家先来探望UIControl为大家提供了如何自定义追踪行为的办法。

-(void)viewDidLoad{

// ViewController.m

NSLog(@"sender = %@",sender);

-(void)touchesBegan:(NSSet<UITouch*>*)toucheswithEvent:(UIEvent*)event

设若稳重研商,会意识贰个珠璧交辉的主题材料。大家来看看实例中ViewController(target)与ImageControl实例(control)的引用关系,如下图所示:

When you call this method, target is not retained.

[controladdTarget:selfaction:@selector(tapImageControl:)forControlEvents:UIControlEventTouchUpInside];

但是,这么些都以UIControl开放出来的接口。大家依旧想要斟酌一下,UIControl是如何去管理Target-Action的吧?

本文由金沙澳门官网网址发布于电脑系统,转载请注明出处:上学笔记

关键词: