123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- #ifdef SHOULD_COMPILE_LOOKIN_SERVER
- //
- // LKS_EventHandlerMaker.m
- // LookinServer
- //
- // Created by Li Kai on 2019/8/7.
- // https://lookin.work
- //
- #import "LKS_EventHandlerMaker.h"
- #import "LookinTuple.h"
- #import "LookinEventHandler.h"
- #import "LookinObject.h"
- #import "LookinWeakContainer.h"
- #import "LookinIvarTrace.h"
- #import "LookinServerDefines.h"
- #import "LKS_GestureTargetActionsSearcher.h"
- #import "LKS_MultiplatformAdapter.h"
- @implementation LKS_EventHandlerMaker
- + (NSArray<LookinEventHandler *> *)makeForView:(UIView *)view {
- if (!view) {
- return nil;
- }
-
- NSMutableArray<LookinEventHandler *> *allHandlers = nil;
-
- if ([view isKindOfClass:[UIControl class]]) {
- NSArray<LookinEventHandler *> *targetActionHandlers = [self _targetActionHandlersForControl:(UIControl *)view];
- if (targetActionHandlers.count) {
- if (!allHandlers) {
- allHandlers = [NSMutableArray array];
- }
- [allHandlers addObjectsFromArray:targetActionHandlers];
- }
- }
-
- NSArray<LookinEventHandler *> *gestureHandlers = [self _gestureHandlersForView:view];
- if (gestureHandlers.count) {
- if (!allHandlers) {
- allHandlers = [NSMutableArray array];
- }
- [allHandlers addObjectsFromArray:gestureHandlers];
- }
-
- return allHandlers.copy;
- }
- + (NSArray<LookinEventHandler *> *)_gestureHandlersForView:(UIView *)view {
- if (view.gestureRecognizers.count == 0) {
- return nil;
- }
- NSArray<LookinEventHandler *> *handlers = [view.gestureRecognizers lookin_map:^id(NSUInteger idx, __kindof UIGestureRecognizer *recognizer) {
- LookinEventHandler *handler = [LookinEventHandler new];
- handler.handlerType = LookinEventHandlerTypeGesture;
- handler.eventName = NSStringFromClass([recognizer class]);
-
- NSArray<LookinTwoTuple *> *targetActionInfos = [LKS_GestureTargetActionsSearcher getTargetActionsFromRecognizer:recognizer];
- handler.targetActions = [targetActionInfos lookin_map:^id(NSUInteger idx, LookinTwoTuple *rawTuple) {
- NSObject *target = ((LookinWeakContainer *)rawTuple.first).object;
- if (!target) {
- // 该 target 已被释放
- return nil;
- }
- LookinStringTwoTuple *newTuple = [LookinStringTwoTuple new];
- newTuple.first = [LKS_Helper descriptionOfObject:target];
- newTuple.second = (NSString *)rawTuple.second;
- return newTuple;
- }];
- handler.inheritedRecognizerName = [self _inheritedRecognizerNameForRecognizer:recognizer];
- handler.gestureRecognizerIsEnabled = recognizer.enabled;
- if (recognizer.delegate) {
- handler.gestureRecognizerDelegator = [LKS_Helper descriptionOfObject:recognizer.delegate];
- }
- handler.recognizerIvarTraces = [recognizer.lks_ivarTraces lookin_map:^id(NSUInteger idx, LookinIvarTrace *trace) {
- return [NSString stringWithFormat:@"(%@ *) -> %@", trace.hostClassName, trace.ivarName];
- }];
-
- handler.recognizerOid = [recognizer lks_registerOid];
- return handler;
- }];
- return handlers;
- }
- + (NSString *)_inheritedRecognizerNameForRecognizer:(UIGestureRecognizer *)recognizer {
- if (!recognizer) {
- NSAssert(NO, @"");
- return nil;
- }
-
- static NSArray<Class> *baseRecognizers;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- // 注意这里 UIScreenEdgePanGestureRecognizer 在 UIPanGestureRecognizer 前面,因为 UIScreenEdgePanGestureRecognizer 继承于 UIPanGestureRecognizer
- #if TARGET_OS_TV
- baseRecognizers = @[[UILongPressGestureRecognizer class],
- [UIPanGestureRecognizer class],
- [UISwipeGestureRecognizer class],
- [UITapGestureRecognizer class]];
- #elif TARGET_OS_VISION
- baseRecognizers = @[[UILongPressGestureRecognizer class],
- [UIPanGestureRecognizer class],
- [UISwipeGestureRecognizer class],
- [UIRotationGestureRecognizer class],
- [UIPinchGestureRecognizer class],
- [UITapGestureRecognizer class]];
- #else
- baseRecognizers = @[[UILongPressGestureRecognizer class],
- [UIScreenEdgePanGestureRecognizer class],
- [UIPanGestureRecognizer class],
- [UISwipeGestureRecognizer class],
- [UIRotationGestureRecognizer class],
- [UIPinchGestureRecognizer class],
- [UITapGestureRecognizer class]];
- #endif
- });
-
- __block NSString *result = @"UIGestureRecognizer";
- [baseRecognizers enumerateObjectsUsingBlock:^(Class _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- if ([recognizer isMemberOfClass:obj]) {
- // 自身就是基本款,则直接置为 nil
- result = nil;
- *stop = YES;
- return;
- }
- if ([recognizer isKindOfClass:obj]) {
- result = NSStringFromClass(obj);
- *stop = YES;
- return;
- }
- }];
- return result;
- }
- + (NSArray<LookinEventHandler *> *)_targetActionHandlersForControl:(UIControl *)control {
- static dispatch_once_t onceToken;
- static NSArray<NSNumber *> *allEvents = nil;
- dispatch_once(&onceToken,^{
- allEvents = @[@(UIControlEventTouchDown), @(UIControlEventTouchDownRepeat), @(UIControlEventTouchDragInside), @(UIControlEventTouchDragOutside), @(UIControlEventTouchDragEnter), @(UIControlEventTouchDragExit), @(UIControlEventTouchUpInside), @(UIControlEventTouchUpOutside), @(UIControlEventTouchCancel), @(UIControlEventValueChanged), @(UIControlEventEditingDidBegin), @(UIControlEventEditingChanged), @(UIControlEventEditingDidEnd), @(UIControlEventEditingDidEndOnExit)];
- if (@available(iOS 9.0, *)) {
- allEvents = [allEvents arrayByAddingObject:@(UIControlEventPrimaryActionTriggered)];
- }
- });
- NSSet *allTargets = control.allTargets;
-
- if (!allTargets.count) {
- return nil;
- }
-
- NSMutableArray<LookinEventHandler *> *handlers = [NSMutableArray array];
-
- [allEvents enumerateObjectsUsingBlock:^(NSNumber * _Nonnull eventNum, NSUInteger idx, BOOL * _Nonnull stop) {
- UIControlEvents event = [eventNum unsignedIntegerValue];
-
- NSMutableArray<LookinStringTwoTuple *> *targetActions = [NSMutableArray array];
-
- [allTargets enumerateObjectsUsingBlock:^(id _Nonnull target, BOOL * _Nonnull stop) {
- NSArray<NSString *> *actions = [control actionsForTarget:target forControlEvent:event];
- [actions enumerateObjectsUsingBlock:^(NSString * _Nonnull action, NSUInteger idx, BOOL * _Nonnull stop) {
- LookinStringTwoTuple *tuple = [LookinStringTwoTuple new];
- tuple.first = [LKS_Helper descriptionOfObject:target];
- tuple.second = action;
- [targetActions addObject:tuple];
- }];
- }];
-
- if (targetActions.count) {
- LookinEventHandler *handler = [LookinEventHandler new];
- handler.handlerType = LookinEventHandlerTypeTargetAction;
- handler.eventName = [self _nameFromControlEvent:event];
- handler.targetActions = targetActions.copy;
- [handlers addObject:handler];
- }
- }];
-
- return handlers;
- }
- + (NSString *)_nameFromControlEvent:(UIControlEvents)event {
- static dispatch_once_t onceToken;
- static NSDictionary<NSNumber *, NSString *> *eventsAndNames = nil;
- dispatch_once(&onceToken,^{
- NSMutableDictionary<NSNumber *, NSString *> *eventsAndNames_m = @{
- @(UIControlEventTouchDown): @"UIControlEventTouchDown",
- @(UIControlEventTouchDownRepeat): @"UIControlEventTouchDownRepeat",
- @(UIControlEventTouchDragInside): @"UIControlEventTouchDragInside",
- @(UIControlEventTouchDragOutside): @"UIControlEventTouchDragOutside",
- @(UIControlEventTouchDragEnter): @"UIControlEventTouchDragEnter",
- @(UIControlEventTouchDragExit): @"UIControlEventTouchDragExit",
- @(UIControlEventTouchUpInside): @"UIControlEventTouchUpInside",
- @(UIControlEventTouchUpOutside): @"UIControlEventTouchUpOutside",
- @(UIControlEventTouchCancel): @"UIControlEventTouchCancel",
- @(UIControlEventValueChanged): @"UIControlEventValueChanged",
- @(UIControlEventEditingDidBegin): @"UIControlEventEditingDidBegin",
- @(UIControlEventEditingChanged): @"UIControlEventEditingChanged",
- @(UIControlEventEditingDidEnd): @"UIControlEventEditingDidEnd",
- @(UIControlEventEditingDidEndOnExit): @"UIControlEventEditingDidEndOnExit",
- }.mutableCopy;
- if (@available(iOS 9.0, *)) {
- eventsAndNames_m[@(UIControlEventPrimaryActionTriggered)] = @"UIControlEventPrimaryActionTriggered";
- }
- eventsAndNames = eventsAndNames_m.copy;
- });
-
- NSString *name = eventsAndNames[@(event)];
- return name;
- }
- @end
- #endif /* SHOULD_COMPILE_LOOKIN_SERVER */
|