UIControl:
控件类的抽象基类
提供跟踪触摸事件的方法有:
跟踪开始:
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
跟踪移动:
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
跟踪结束:
- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
跟踪取消:
- (void)cancelTrackingWithEvent:(UIEvent *)event
对应UIResponse提供的四个方法:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
区别:
UIControl的是针对单点触摸,而UIResponse可能是多点触摸。
由于UIControl本身是视图,所以它实际上也继承了UIResponse的这四个方法
/*针对控件的触摸事件发生时,这两组方法都会被调用,而且互不干涉*/
BOOL tracking属性:
判断当前对象是否正在追踪触摸操作
BOOL touchInside属性:
判断当前触摸点是否在控件区域类
注意:
1.当我们的触摸点沿着屏幕移出控件区域名,还是会继续追踪触摸操作,cancelTrackingWithEvent:消息并未被发送
2用于判定touchInside为YES的区域会比控件区域要大
Target-Action机制:
Target-action是一种设计模式,直译过来就是“目标-行为”
如:
[button addTarget:self action:@selector(tapButton:) forControlEvents:UIControlEventTouchUpInside];
/*
当按钮的点击事件发生时,会将消息发送到target(此处即为self对象),并由target对象的tapButton:方法来处理相应的事件
实现了:目标-行为
*/
Target-Action机制由两部分组成:
1.目标对象:指定最终处理事件的对象
2.行为Selector:处理事件的方法
观察或修改分发到target对象的行为消息:
对于一个给定的事件:
1.UIControl会调用sendAction:to:forEvent:来将行为消息转发到UIApplication对象
2.再由UIApplication对象调用其sendAction:to:fromSender:forEvent:方法来将消息分发到指定的target上,
3.而如果我们没有指定target,则会将事件分发到响应链上第一个想处理消息的对象上
4.而如果子类想监控或修改这种行为的话,则可以重写这个方法
UIControl对象调用
sendActionsForControlEvents:方法,
也会触发sendAction:to:forEvent:方法
示范例子:
//创建UIControl的一个子类,以图片为背景,然后在下方显示一个Label的结合类型
@interface ImageControl : UIControl
- (instancetype)initWithFrame:(CGRect)frame title:(NSString *)title image:(UIImage *)image;
@end
//将外部添加的Target-Action放在空间内部处理:
//重写sendAction:to:fromSender:forEvent:方法
// ImageControl.m
- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
// 将事件传递到对象本身来处理
[super sendAction:@selector(handleAction:) to:self forEvent:event];
}
- (void)handleAction:(id)sender {
NSLog(@"handle Action");
}
// ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
ImageControl *control = [[ImageControl alloc] initWithFrame:(CGRect){50.0f, 100.0f, 200.0f, 300.0f} title:@"This is a demo" image:[UIImage imageNamed:@"demo"]];
// ...
[control addTarget:self action:@selector(tapImageControl:) forControlEvents:UIControlEventTouchUpInside];
[control sendActionsForControlEvents:UIControlEventTouchUpInside];//未点击也触发了UIControlEventTouchUpInside事件
}
- (void)tapImageControl:(id)sender {
NSLog(@"sender = %@", sender);
}
/*
由于我们重写了sendAction:to:forEvent:方法,
所以最后处理事件的Selector是ImageControl的handleAction:方法,
而不是ViewController的tapImageControl:方法。
*/
Target-Action的管理:
为控件对象添加删除Target-Action操作:
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
- (void)removeTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
获取控件对象所有相关的target对象:
-(NSSet *)allTargets;
获取某个target对象的事件相关的所有action:
actionsForTarget:forControlEvent:
UIControl内部:
存在一个targetAction可变数组,元素是UIControlTargetAction对象
UIControlTargetAction类是一个私有类:
@interface UIControlTargetAction : NSObject {
SEL _action;
BOOL _cancelled;
unsigned int _eventMask;
id _target;//内部隐藏的弱引用
}
@property (nonatomic) BOOL cancelled;
- (void).cxx_destruct;
- (BOOL)cancelled;
- (void)setCancelled:(BOOL)arg1;
@end
维护了一个Target-Action必须三要素:
target
action
eventMask
UIImage:
不可变性:
UIImage对象是不可变的,所以一旦创建后,我们就不能再改变它的属性。
想修改UIImage对象的一些属性,则可以使用便捷方法和自定义的参数值来创建图像的一份拷贝
UIImage没有提供访问底层图片数据的方法
可以使用UIImagePNGRepresentation或UIImageJPEGRepresentation方法来获取包含PNG或JPG格式的数据的NSData对象
内存管理:
同一时间加载大量的图片,就可能占用大量的系统内存。
init(named:)方法初始化的图片,图片资源(而不是UIImage对象)会先从缓存寻找,没有再加载图片并存入缓存中
此方法适用频繁使用同一份图片数据初始化UIImage,但是会让内存一直持有该图片资源浪费内存
只需写图片名,不需要指定1x,2x,3x;若图片为png格式,则连图片后缀也不需要写
在二级线程中调用可能会导致崩溃,尽量在主线程中调用这个方法。
imageWithContentsOfFile:方法每次从路径中获取图片数据不会缓存起图片数据,可以减少内存资源消耗