概述
UIView支持手势添加,UIControl继承自UIControl,添加了一些常见手势,这些常见手势会触发一些预定义的UIControlEvent
UIControlEvents
typedef NS_OPTIONS(NSUInteger, UIControlEvents) {
UIControlEventTouchDown = 1 << 0, // on all touch downs
UIControlEventTouchDownRepeat = 1 << 1, // on multiple touchdowns (tap count > 1)
UIControlEventTouchDragInside = 1 << 2,
UIControlEventTouchDragOutside = 1 << 3,
UIControlEventTouchDragEnter = 1 << 4,
UIControlEventTouchDragExit = 1 << 5,
UIControlEventTouchUpInside = 1 << 6,
UIControlEventTouchUpOutside = 1 << 7,
UIControlEventTouchCancel = 1 << 8,
UIControlEventValueChanged = 1 << 12, // sliders, etc.
UIControlEventPrimaryActionTriggered NS_ENUM_AVAILABLE_IOS(9_0) = 1 << 13, // semantic action: for buttons, etc.
UIControlEventEditingDidBegin = 1 << 16, // UITextField
UIControlEventEditingChanged = 1 << 17,
UIControlEventEditingDidEnd = 1 << 18,
UIControlEventEditingDidEndOnExit = 1 << 19, // 'return key' ending editing
UIControlEventAllTouchEvents = 0x00000FFF, // for touch events
UIControlEventAllEditingEvents = 0x000F0000, // for UITextField
UIControlEventApplicationReserved = 0x0F000000, // range available for application use
UIControlEventSystemReserved = 0xF0000000, // range reserved for internal framework use
UIControlEventAllEvents = 0xFFFFFFFF
};
UIControlEvents bitmask形式保存UIControlEvent,可以同时保存多个UIControlEvent
手势触发的UIControlEvent
UIControlEventTouchDown = 1 << 0, // on all touch downs
UIControlEventTouchDownRepeat = 1 << 1, // on multiple touchdowns (tap count > 1)
UIControlEventTouchDragInside = 1 << 2,
UIControlEventTouchDragOutside = 1 << 3,
UIControlEventTouchDragEnter = 1 << 4,
UIControlEventTouchDragExit = 1 << 5,
UIControlEventTouchUpInside = 1 << 6,
UIControlEventTouchUpOutside = 1 << 7,
UIControlEventTouchCancel = 1 << 8,
解释
- UIControlEventTouchDown:bounds内点击,highlighted = 1
- UIControlEventTouchDownRepeat:bounds内短时间内连击(大于1次),在触发TouchDownRepeat之前先触发TouchDown,然后触发DownRepeat,然后触发TouchUpInside,因此如果连击3次,依次触发的事件为TouchDown->TouchUpInside->TouchDown->TouchDownRepeat->TouchUpInside->TouchDown->TouchDownRepeat->TouchUpInside
- UIControlEventTouchDragInside:bounds内拖动,持续触发,highlighted = 1
- UIControlEventTouchDragOutside:bounds内拖动出bounds,在bounds外拖动,持续触发,highlighted = 0
- UIControlEventTouchDragEnter:bounds内拖动出bounds,然后再拖动回bounds内临界,不持续触发
- UIControlEventTouchDragExit:bounds内拖动出bounds临界,不持续触发
- UIControlEventTouchUpInside:bounds内释放,highlighted = 0
- UIControlEventTouchUpOutside:bounds内拖动出bounds,在bounds外释放,highlighted = 0
- UIControlEventTouchCancel:取消touch Event
概述
UIView支持手势添加,UIControl继承自UIView,自然支持手势添加,但UIControl在UIView基础上预定义了一些常见手势,这些常见手势定义在UIControlEvents中
UIControlEvents
typedef NS_OPTIONS(NSUInteger, UIControlEvents) {
UIControlEventTouchDown = 1 << 0, // on all touch downs
UIControlEventTouchDownRepeat = 1 << 1, // on multiple touchdowns (tap count > 1)
UIControlEventTouchDragInside = 1 << 2,
UIControlEventTouchDragOutside = 1 << 3,
UIControlEventTouchDragEnter = 1 << 4,
UIControlEventTouchDragExit = 1 << 5,
UIControlEventTouchUpInside = 1 << 6,
UIControlEventTouchUpOutside = 1 << 7,
UIControlEventTouchCancel = 1 << 8,
UIControlEventValueChanged = 1 << 12, // sliders, etc.
UIControlEventPrimaryActionTriggered NS_ENUM_AVAILABLE_IOS(9_0) = 1 << 13, // semantic action: for buttons, etc.
UIControlEventEditingDidBegin = 1 << 16, // UITextField
UIControlEventEditingChanged = 1 << 17,
UIControlEventEditingDidEnd = 1 << 18,
UIControlEventEditingDidEndOnExit = 1 << 19, // 'return key' ending editing
UIControlEventAllTouchEvents = 0x00000FFF, // for touch events
UIControlEventAllEditingEvents = 0x000F0000, // for UITextField
UIControlEventApplicationReserved = 0x0F000000, // range available for application use
UIControlEventSystemReserved = 0xF0000000, // range reserved for internal framework use
UIControlEventAllEvents = 0xFFFFFFFF
};
预定义手势:
UIControlEventTouchDown = 1 << 0, // on all touch downs
UIControlEventTouchDownRepeat = 1 << 1, // on multiple touchdowns (tap count > 1)
UIControlEventTouchDragInside = 1 << 2,
UIControlEventTouchDragOutside = 1 << 3,
UIControlEventTouchDragEnter = 1 << 4,
UIControlEventTouchDragExit = 1 << 5,
UIControlEventTouchUpInside = 1 << 6,
UIControlEventTouchUpOutside = 1 << 7,
UIControlEventTouchCancel = 1 << 8,
event-target-action
// add target/action for particular event. you can call this multiple times and you can specify multiple target/actions for a particular event.
// passing in nil as the target goes up the responder chain. The action may optionally include the sender and the event in that order
// the action cannot be NULL. Note that the target is not retained.
- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
// remove the target/action for a set of events. pass in NULL for the action to remove all actions for that target
- (void)removeTarget:(nullable id)target action:(nullable SEL)action forControlEvents:(UIControlEvents)controlEvents;
- (nullable NSArray<nsstring> *)actionsForTarget:(nullable id)target forControlEvent:(UIControlEvents)controlEvent; // single event. returns NSArray of NSString selector names. returns nil if none
- (UIControlEvents)allControlEvents; // list of all events that have at least one action
// get info about target & actions. this makes it possible to enumerate all target/actions by checking for each event kind
- (NSSet *)allTargets; // set may include NSNull to indicate at least one nil target
- (void)displayIvarList:(Class)aClass
{
unsigned int varCnt = 0;
Ivar *classIvars = class_copyIvarList(aClass, &varCnt);
for(int i = 0; i < varCnt; i++)
{
Ivar thisIvar = classIvars[i];
NSString *varName = [NSString stringWithUTF8String:ivar_getName(thisIvar)];
NSString *varType = [NSString stringWithUTF8String:ivar_getTypeEncoding(thisIvar)];
NSLog(@"varName = %@, varType = %@", varName, varType);
}
free(classIvars);
}
[self displayIvarList:[UIControl class]];
output:
varName = _targetActions, varType = @"NSMutableArray"
varName = _previousPoint, varType = {CGPoint="x"d"y"d}
varName = _downTime, varType = d
varName = _controlFlags, varType = {?="disabled"b1"tracking"b1"touchInside"b1"touchDragged"b1"requiresDisplayOnTracking"b1"highlighted"b1"dontHighlightOnTouchDown"b1"delayActions"b1"allowActionsToQueue"b1"pendingUnhighlight"b1"selected"b1"verticalAlignment"b2"horizontalAlignment"b2"wasLastHighlightSuccessful"b1"touchHasHighlighted"b1}
分析:
UIControl内含一个NSMutableArray结构,对象类型为event-target-action,event-target-action不能重复,当event触发时,从头依序遍历NSMutableArray,依序调用与event相等的event-target-action中的target-action
注意:
- addTarget:action:forControlEvents: ——target可以为nil,controlEvents是UIControlEvents组合,当event触发时,target不为nil时,依序调用与event相等的event-action-action中的target-action,如果找不到target-action,crash;target为nil时,以responder chain顺序寻找action,找到调用,找不到do nothing,不会crash
- removeTarget:action:forControlEvents:——target可以为nil,action被ignored,controlEvents是UIControlEvents组合,target不为nil时,删除event-target相等的所有event-target-action,target为nil时,删除event相等的所有event-target-action
- actionForTarget:target:forCOntrolEvent:——target为nil,返回也nil,无意义,controlEvent是单一UIControlEvents,不能是UIControlEvents组合,否则方法意义不大,返回event-target相等的action(SEL) NSArray
- allControlEvents——返回NSMutableArray中的所有event
- allTargets——返回NSMutableArray中的所有target,包括NSNull,如果addTarget:action:forControlEvents: 时target传了nil
注:target参数是弱引用