iOS 개발 의 터치 이벤트 및 제스처

iOS 의 이 벤트 는 터치 이벤트,가속 이벤트,원 격 제어 이벤트 등 세 가지 로 나 뉜 다.UIResponder 의 대상 을 계승 해야만 이 벤트 를 접수 하고 처리 할 수 있 으 며 이 를'응답 자 대상'이 라 고 합 니 다.UIApplication,UIViewController,UIView 는 모두 UIResponder 에서 계승 합 니 다.UIResponsder 내부 에서 제공 하 는 방법 으로 이 벤트 를 처리 합 니 다.
터치 이벤트:touches Began,touches Moved,touches Ended,touches Cancelled
가속기 사건:motion Began,motion Ended,motion Canceled
원 격 제어 이벤트:remoteControl Received WithEvent
UIVeiw 의 터치 이벤트 처리 과정:

/**
 *        view   
 *
 * @param touches <#touches description#>
 * @param event  <#event description#>
 */
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
   
  NSLog(@"%s",__func__);
}
 
/**
 *     view      
 *
 * @param touches <#touches description#>
 * @param event  <#event description#>
 */
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  NSLog(@"%s",__func__);
}
 
/**
 *      view   
 *
 * @param touches <#touches description#>
 * @param event  <#event description#>
 */
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
   
  NSLog(@"%s",__func__);
}
 
/**
 *                
 *
 * @param touches <#touches description#>
 * @param event  <#event description#>
 */
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
   
  NSLog(@"%s",__func__);
}
한 번 의 터치 동작 은 반드시 touches Beagn,touches Moved 와 touches Ended 라 는 세 가지 방법 을 호출 할 것 이다.
이 몇 가지 터치 방법 에 대해 서 는 먼저 UITouch 라 는 대상 을 알 아야 한다.한 손가락 이 화면 을 만 지면 연 결 된 UITouch 대상 이 생기 고 한 손가락 은 UITouch 대상 에 대응 합 니 다.이 대상 에는 터치 의 위치,시간,단계 등 이번 터치 의 정보 가 저장 되 어 있 으 며 손가락 이 이동 할 때 시스템 은 같은 UITouch 대상 을 업데이트 합 니 다.손가락 이 있 는 터치 위치 정 보 를 계속 저장 할 수 있 도록 한다.손가락 이 화면 을 떠 날 때 시스템 은 대응 하 는 UITouch 대상 을 소각 합 니 다.

@interface UITouch : NSObject
 
@property(nonatomic,readonly) NSTimeInterval   timestamp;
@property(nonatomic,readonly) UITouchPhase    phase;
@property(nonatomic,readonly) NSUInteger     tapCount;  // touch down within a certain point within a certain amount of time
 
// majorRadius and majorRadiusTolerance are in points
// The majorRadius will be accurate +/- the majorRadiusTolerance
@property(nonatomic,readonly) CGFloat majorRadius NS_AVAILABLE_IOS(8_0);
@property(nonatomic,readonly) CGFloat majorRadiusTolerance NS_AVAILABLE_IOS(8_0);
 
@property(nullable,nonatomic,readonly,strong) UIWindow            *window;
@property(nullable,nonatomic,readonly,strong) UIView             *view;
@property(nullable,nonatomic,readonly,copy)  NSArray <UIGestureRecognizer *> *gestureRecognizers NS_AVAILABLE_IOS(3_2);
 
//      
- (CGPoint)locationInView:(nullable UIView *)view;
//           
- (CGPoint)previousLocationInView:(nullable UIView *)view;
 
// Force of the touch, where 1.0 represents the force of an average touch
@property(nonatomic,readonly) CGFloat force NS_AVAILABLE_IOS(9_0);
// Maximum possible force with this input mechanism
@property(nonatomic,readonly) CGFloat maximumPossibleForce NS_AVAILABLE_IOS(9_0);
 
@end
eg:손가락 이 움 직 이면 서 view 를 움 직 이게 합 니 다.

/**
 *     view      
 *
 * @param touches <#touches description#>
 * @param event  <#event description#>
 */
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  NSLog(@"%s",__func__);
   
  //  UITouch  
  UITouch *touch = [touches anyObject];
   
  //        
  CGPoint curP = [touch locationInView:self];
   
  //         
  CGPoint preP = [touch previousLocationInView:self];
   
  //  x    
  CGFloat offsetX = curP.x - preP.x;
   
  //  y    
  CGFloat offsetY = curP.y = preP.y;
   
  //  view   
  self.transform = CGAffineTransformTranslate(self.transform, offsetX, offsetY);
}
UITouch 대상 에 저 장 된 위치 정보 에 따라 이 루어 집 니 다.
이벤트 생 성과 전달:
터치 이벤트 가 발생 하면 시스템 은 이 이 벤트 를 UIApplication 에서 관리 하 는 이벤트 대기 열 에 추가 합 니 다.UIApplication 은 대기 열 에서 맨 앞 에 있 는 이 벤트 를 꺼 내 프로그램의 주 창 에 보 냅 니 다.주 창 은 보기 계층 구조 에서 가장 적합 한 보 기 를 찾 아 터치 이 벤트 를 처리 합 니 다.터치 이벤트 의 전달 은 부모 컨트롤 에서 하위 컨트롤 로 전 달 됩 니 다.부모 컨트롤 이 터치 이 벤트 를 받 아들 일 수 없다 면 하위 컨트롤 은 터치 이 벤트 를 받 아들 일 수 없습니다.
어떻게 가장 적합 한 컨트롤 을 찾 아서 사건 을 처리 합 니까?먼저 터치 사건 을 받 아들 일 수 있 는 지 판단 합 니까?터치 점 은 자신 에 게 있 습 니까?하위 컨트롤 을 뒤로 옮 겨 다 니 며 이전 두 단 계 를 반복 합 니 다.조건 에 맞 는 하위 컨트롤 이 없 으 면 스스로 처리 하 는 것 이 가장 적합 합 니 다.
컨트롤 은 hitTest:withEvent:방법 으로 가장 적합 한 view 를 찾 습 니 다.pointInside 라 는 방법 으로 이 점 이 방법 호출 자 즉 컨트롤 에 있 는 지 판단 합 니 다.
hitTest 방법의 밑바닥 실현:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
   
  //               
  if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) {
    return nil;
  }
   
  //             
  if ([self pointInside:point withEvent:event] == NO) {
    return nil;
  }
   
  //            
  NSInteger count = self.subviews.count;
  for (NSInteger i = count - 1; i >= 0; i--) {
    UIView *childView = self.subviews[i];
     
    //                     
    CGPoint childPoint = [self convertPoint:point toView:childView];
     
    //    hitTest        view
    UIView *fitView = [childView hitTest:childPoint withEvent:event];
     
    if (fitView) {
      return fitView;
    }
  }
   
  //    ,         view,    
  return self;
   
}
그러나 터치 이 벤트 를 터치 방식 으로 감청 하 는 것 은 단점 이 있다.예 를 들 어 뷰 를 사용자 정의 해 야 하기 때문에 iOS 3.2 이후 애플 은 제스처 인식 기능 인 UIGesture Recognizer 를 출시 했다.UIGesture Recognizer 는 추상 적 인 클래스 로 하위 클래스 가 구체 적 인 제스처 를 처리 할 수 있 습 니 다.
구체 적 으로 다음 과 같은 몇 가지 손짓 이 있다.

//    
//  UITapGestureRecognizer *tap = [UITapGestureRecognizer alloc]initWithTarget:<#(nullable id)#> action:<#(nullable SEL)#>
   
  //            
//  UILongPressGestureRecognizer *longP = [UILongPressGestureRecognizer alloc]initWithTarget:<#(nullable id)#> action:<#(nullable SEL)#>
   
  //            
//  UISwipeGestureRecognizer *swipe = [UISwipeGestureRecognizer alloc]initWithTarget:<#(nullable id)#> action:<#(nullable SEL)#>
   
  //    
//  UIRotationGestureRecognizer *rotation = [UIRotationGestureRecognizer alloc]initWithTarget:<#(nullable id)#> action:<#(nullable SEL)#>
 
  //    
//  UIPinchGestureRecognizer *pinch = [UIPinchGestureRecognizer alloc]initWithTarget:<#(nullable id)#> action:<#(nullable SEL)#>
   
  //    
//  UIPanGestureRecognizer *pan = [UIPanGestureRecognizer alloc]initWithTarget:<#(nullable id)#> action:<#(nullable SEL)#>
실제 운용:

@interface ViewController ()<UIGestureRecognizerDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
 
@end
 
@implementation ViewController
 
- (void)viewDidLoad {
  [super viewDidLoad];
 
  [self setUpPinch];
   
  [self setUpRotation];
 
  [self setUpPan];
   
}
#pragma mark -       
//           
//- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
//{
//  return NO;
//}
 
//             ,          
//   yes        
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
  return YES;
}
 
//             
//- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
//  //         
//  CGPoint curP = [touch locationInView:self.imageView];
//  
//  if (curP.x < self.imageView.bounds.size.width * 0.5) {
//    return NO;
//  }else{
//    return YES;
//  }
//}
 
 
#pragma mark -     
 
- (void)setUpTap
{
  //       
  UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
   
  tap.delegate = self;
   
  [_imageView addGestureRecognizer:tap];
}
 
- (void)tap:(UITapGestureRecognizer *)tap
{
  NSLog(@"%s",__func__);
}
 
#pragma mark -     
//        
- (void)setUpLongPress
{
  UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
   
  [self.imageView addGestureRecognizer:longPress];
}
 
 
- (void)longPress:(UILongPressGestureRecognizer *)longPress
{
   
  if (longPress.state == UIGestureRecognizerStateBegan) {
     
    NSLog(@"%s",__func__);
  }
}
 
#pragma mark -   
- (void)setUpSwipe
{
  //           
  UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe)];
   
  swipe.direction = UISwipeGestureRecognizerDirectionUp;
   
  [self.imageView addGestureRecognizer:swipe];
   
  //                    ,          ,             
  //           
  UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe)];
   
  swipeDown.direction = UISwipeGestureRecognizerDirectionDown;
   
  [self.imageView addGestureRecognizer:swipeDown];
 
   
}
 
- (void)swipe
{
  NSLog(@"%s",__func__);
}
 
#pragma mark -     
- (void)setUpRotation
{
  UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotation:)];
  rotation.delegate = self;
  [self.imageView addGestureRecognizer:rotation];
}
 
//                      
- (void)rotation:(UIRotationGestureRecognizer *)rotation
{
   
  self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, rotation.rotation);
   
  //   
  rotation.rotation = 0;
   
  //          
  NSLog(@"%f",rotation.rotation);
}
 
#pragma mark -   
- (void)setUpPinch
{
  UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];
  pinch.delegate = self;
  [self.imageView addGestureRecognizer:pinch];
}
 
- (void)pinch:(UIPinchGestureRecognizer *)pinch
{
  self.imageView.transform = CGAffineTransformScale(self.imageView.transform, pinch.scale, pinch.scale);
   
  //   
   
  pinch.scale = 1;
}
 
#pragma mark -   
- (void)setUpPan
{
  UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
   
   
  [self.imageView addGestureRecognizer:pan];
}
 
- (void)pan:(UIPanGestureRecognizer *)pan
{
  //         
  // CGPoint curP = [pan locationInView:self.imageView];
   
  //     
  //        ,           
  CGPoint transP = [pan translationInView:self.imageView];
   
  self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, transP.x, transP.y);
   
  //   
  [pan setTranslation:CGPointZero inView:self.imageView];
   
 // NSLog(@"%@",NSStringFromCGPoint(curP));
}
 
@end
이상 은 iOS 터치 이벤트 와 제스처 에 관 한 내용 소개 입 니 다.iOS 프로 그래 밍 을 배 우 는 데 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기