본문 바로가기

iOS

iOS 터치-2

728x90
반응형
SMALL

iOS 에서 전기용량 감지 방식으로 감지 한 후 일어나는 일

iOS에서 전기용량 감지 방식을 사용하여 터치 이벤트가 감지되면, 다음과 같은 일이 일어납니다.

  1. 터치 이벤트가 발생한 위치와 크기를 감지합니다.
  2. 해당 위치와 크기에 대한 터치 이벤트 정보를 앱에 전달합니다.
  3. 앱은 해당 터치 이벤트 정보를 처리하고, 그에 따른 동작을 수행합니다. 이를 통해 사용자는 버튼을 클릭하거나, 스크롤을 하거나, 줌을 하거나 등의 다양한 제스쳐를 수행할 수 있습니다.
  4. 만약 앱에서 제스쳐 인식 기능을 사용하고 있다면, 감지된 터치 이벤트 정보를 분석하여 해당하는 제스쳐를 인식합니다. 

다음은 제스쳐 인식 예제 코드 입니다. swipe 는 pinch 를 주석처리하고 확인해 보시면 됩니다 :)

import UIKit

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        // Tap Gesture
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        view.addGestureRecognizer(tapGesture)
        
        // Long Press Gesture
        let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))
        view.addGestureRecognizer(longPressGesture)
        
        // Swipe Gesture
        let swipeRightGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(_:)))
        swipeRightGesture.direction = .right
        view.addGestureRecognizer(swipeRightGesture)
        
        let swipeLeftGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(_:)))
        swipeLeftGesture.direction = .left
        view.addGestureRecognizer(swipeLeftGesture)
        
        // Pinch Gesture
        let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(_:)))
        view.addGestureRecognizer(pinchGesture)
        
        // Rotation Gesture
        let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotation(_:)))
        view.addGestureRecognizer(rotationGesture)
        
        // Pan Gesture 드래그
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
        view.addGestureRecognizer(panGesture)
        
        // Edge Pan Gesture 양쪽모서리
        let edgePanGesture = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(handleEdgePan(_:)))
        edgePanGesture.edges = .left
        view.addGestureRecognizer(edgePanGesture)
        
//        iOS 사용 X
//        let hoverGestureRecognizer = UIHoverGestureRecognizer(target: self, action: #selector(handleHover(_:)))
//
//               // 뷰에 제스처 추가
//               view.addGestureRecognizer(hoverGestureRecognizer)

        let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap(_:)))
           doubleTapGesture.numberOfTapsRequired = 2
           view.addGestureRecognizer(doubleTapGesture)

        
    }
    
    @objc func handleTap(_ gesture: UITapGestureRecognizer) {
        print("Tap gesture recognized")
    }
    
    @objc func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
        if gesture.state == .began {
            print("Long press gesture recognized")
        }
    }
    
    @objc func handleSwipe(_ gesture: UISwipeGestureRecognizer) {
        if gesture.direction == .right {
            print("Right swipe gesture recognized")
        } else if gesture.direction == .left {
            print("Left swipe gesture recognized")
        }
    }
    
    @objc func handlePinch(_ gesture: UIPinchGestureRecognizer) {
        let scale = gesture.scale
        print("Pinch gesture recognized with scale: \(scale)")
    }
    
    @objc func handleRotation(_ gesture: UIRotationGestureRecognizer) {
        let rotation = gesture.rotation
        print("Rotation gesture recognized with rotation: \(rotation)")
    }
    
    @objc func handlePan(_ gesture: UIPanGestureRecognizer) {
        let translation = gesture.translation(in: view)
        print("Pan gesture recognized with translation: \(translation)")
    }
    
    @objc func handleEdgePan(_ gesture: UIScreenEdgePanGestureRecognizer) {
        if gesture.state == .recognized {
            print("Edge pan gesture recognized")
        }
    }
    
    @objc func handleHover(_ gesture: UIHoverGestureRecognizer) {
           if gesture.state == .began || gesture.state == .changed {
               view.backgroundColor = .blue
           } else if gesture.state == .ended {
               view.backgroundColor = .white
           }
       }
    @objc func handleDoubleTap(_ gesture: UITapGestureRecognizer) {
        print("Double tap gesture recognized")
    }
}

 

 

 

 UIGestureRecognizer.h 파일 읽기

#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <UIKit/UIKitDefines.h>
#import <UIKit/UICommand.h>
#import <UIKit/UIEvent.h>

위 코드는 Objective-C 언어에서 UIKit 프레임워크의 일부를 가져오는 코드입니다.

NS_HEADER_AUDIT_BEGIN(nullability, sendability)

nullability와 sendability는 Objective-C와 Swift 언어에서 사용되는 개념입니다.

  • nullability: nullability는 포인터 값이 nil일 수 있는지 여부를 지정합니다. Objective-C에서는 nullable, nonnull과 같은 키워드를 사용하여 지정하며, Swift에서는 옵셔널(Optional) 타입으로 표현합니다.
  • sendability: sendability는 Swift에서 사용하는 개념으로, 함수나 메소드 파라미터에 대한 보안 검사를 수행하는 것을 말합니다. @escaping과 @noescape 키워드를 사용하여 지정합니다.
@protocol UIGestureRecognizerDelegate;
@class UIView, UIEvent, UITouch, UIPress;

다음은 UIGestureRecognizer 클래스의 프로토콜 및 클래스 선언입니다.

typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {
    UIGestureRecognizerStatePossible,   // the recognizer has not yet recognized its gesture, but may be evaluating touch events. this is the default state
    
    UIGestureRecognizerStateBegan,      // the recognizer has received touches recognized as the gesture. the action method will be called at the next turn of the run loop
    UIGestureRecognizerStateChanged,    // the recognizer has received touches recognized as a change to the gesture. the action method will be called at the next turn of the run loop
    UIGestureRecognizerStateEnded,      // the recognizer has received touches recognized as the end of the gesture. the action method will be called at the next turn of the run loop and the recognizer will be reset to UIGestureRecognizerStatePossible
    UIGestureRecognizerStateCancelled,  // the recognizer has received touches resulting in the cancellation of the gesture. the action method will be called at the next turn of the run loop. the recognizer will be reset to UIGestureRecognizerStatePossible
    
    UIGestureRecognizerStateFailed,     // the recognizer has received a touch sequence that can not be recognized as the gesture. the action method will not be called and the recognizer will be reset to UIGestureRecognizerStatePossible
    
    // Discrete Gestures – gesture recognizers that recognize a discrete event but do not report changes (for example, a tap) do not transition through the Began and Changed states and can not fail or be cancelled
    UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded // the recognizer has received touches recognized as the gesture. the action method will be called at the next turn of the run loop and the recognizer will be reset to UIGestureRecognizerStatePossible
};

typedef는 C 언어에서 사용되는 키워드로, 특정 자료형에 새로운 이름을 지정할 때 사용됩니다.

NS_ENUM은 Objective-C 언어에서 사용되는 매크로로, 열거형(enum)을 쉽게 정의하고 사용할 수 있도록 도와줍니다.

위 코드에서는 UIGestureRecognizerState라는 열거형을 NSInteger 타입으로 정의하고 있습니다. 이 열거형은 제스처 인식기(gesture recognizer)의 상태를 나타내는 값들을 가지고 있습니다.

 

UIKIT_EXTERN API_AVAILABLE(ios(3.2)) NS_SWIFT_UI_ACTOR

UIKIT_EXTERN은 UIKit 프레임워크에서 정의된 것이며, API_AVAILABLE 매크로는 해당 클래스, 프로퍼티 또는 메소드가 특정 버전의 iOS 이상에서 사용 가능함을 나타냅니다. NS_SWIFT_UI_ACTOR는 Swift에서 액터를 지원하는 Objective-C 클래스에서 사용됩니다. 이 코드 라인은 Objective-C 클래스에서 Swift와 상호 작용하는 데 필요한 메타 정보를 제공합니다.

@interface UIGestureRecognizer : NSObject

UIGestureRecognizer: NSObject 클래스를 상속하는 제스처 인식기 클래스입니다.

- (instancetype)initWithTarget:(nullable id)target action:(nullable SEL)action NS_DESIGNATED_INITIALIZER;

타겟과 액션을 지정하여 초기화하는 이니셜라이저입니다. *NS_DESIGNATED_INITIALIZER 매크로를 사용하여 이니셜라이저 체인에 대한 정보를 컴파일러에게 알립니다.

 

*** NS_DESIGNATED_INITIALIZER 매크로란? ***

NS_DESIGNATED_INITIALIZER 매크로는 Objective-C의 초기화(initialization) 메서드 중에서, 해당 클래스에서 지정된 초기화 메서드(designated initializer)를 가리키는 매크로입니다. designated initializer는 해당 클래스에서 초기화 메서드를 선택하고, 이를 통해 초기화할 때 필요한 모든 프로퍼티를 설정합니다. 따라서 designated initializer를 호출하지 않고 다른 초기화 메서드를 사용할 경우, 이는 초기화 과정에서 필요한 일부 프로퍼티가 설정되지 않아 예기치 않은 결과를 초래할 수 있습니다. NS_DESIGNATED_INITIALIZER 매크로는 이러한 문제를 방지하기 위해, designated initializer를 명시적으로 표시하여 컴파일러에게 알리는 역할을 합니다.

- (instancetype)init;

이 메소드는 초기화를 위한 디자인 패턴 중 하나인 NS_DESIGNATED_INITIALIZER가 적용되지 않은 일반적인 초기화 메소드입니다. 해당 클래스의 인스턴스를 생성할 때 사용되며, 초기화된 객체를 반환합니다.

 

- (nullable instancetype)initWithCoder:(NSCoder *)coder;

인코더(NSCoder)를 이용한 초기화 메소드입니다.

(void)addTarget:(id)target action:(SEL)action; 
// 타겟/액션 쌍을 추가합니다. 여러 개의 타겟/액션을 지정하려면 이 메서드를 여러 번 호출할 수 있습니다.
(void)removeTarget:(nullable id)target action:(nullable SEL)action;
// 지정된 타겟/액션 쌍을 제거합니다. target에 nil을 전달하면 모든 타겟이 일치하고, action도 마찬가지입니다.
@property(nonatomic,readonly) UIGestureRecognizerState state; 
// 현재 제스처 인식기의 상태

@property(nullable,nonatomic,weak) id <UIGestureRecognizerDelegate> delegate; 
// 제스처 인식기의 델리게이트

@property(nonatomic, getter=isEnabled) BOOL enabled; 
// 기본값은 YES입니다. 비활성화된 제스처 인식기는 터치를받지 않습니다. NO로 변경하면 현재 제스처를 인식하고있는 경우 제스처 인식기가 취소됩니다.

// UIGestureRecognizer는 해당 뷰 및 해당 뷰의 하위 뷰에서 히트 테스트 된 터치를받습니다.
@property(nullable, nonatomic,readonly) UIView *view; 
// 제스처가 연결된 뷰. addGestureRecognizer : 메서드를 사용하여 제스처 인식기를 UIView에 추가하여 설정합니다.

@property(nonatomic) BOOL cancelsTouchesInView; 
// 기본값은 YES입니다. 이 제스처 일부로 인식 된 모든 터치 또는 프레스에 대해 touchesCancelled : withEvent : 또는 pressesCancelled : withEvent :가 호출되어 보내지도록합니다.
@property(nonatomic) BOOL delaysTouchesBegan; 
// 기본값은 NO입니다. 이 제스처가 인식 실패 후에 대상 뷰로 전달되기 전에 대상 뷰로 모든 터치 또는 프레스 이벤트가 전달되도록합니다.이 제스처의 일부로 인식 될 수있는 터치 또는 프레스를 처리하지 않도록하려면 YES로 설정하십시오.
@property(nonatomic) BOOL delaysTouchesEnded; 
// 기본값은 YES입니다. touchesEnded 또는 pressesEnded 이벤트가 인식 실패 후에 대상 뷰로 전달되도록합니다. 이렇게하면 제스처의 일부인 터치 또는 프레스를 제스처가 인식되면 취소 할 수 있습니다.

@property(nonatomic, copy) NSArray<NSNumber *> *allowedTouchTypes API_AVAILABLE(ios(9.0)); // UITouchTypes의 배열입니다. NSNumbers로.
@property(nonatomic, copy) NSArray<NSNumber *> *allowedPressTypes API_AVAILABLE(ios(9.0)); // UIPressTypes의 배열입니다. NSNumbers로.

// 제스처 인식기가 동시에 다른 터치 유형의 터치를 고려할지 여부를 나타냅니다.
// NO 인 경우 allowedTouchTypes와 일치하는 모든 터치를받습니다.
// YES 인 경우 특정 유형의 터치를받으면 다른 유형의 새로운 터치를 무시합니다. UIGestureRecognizerStatePossible로 재설정 될 때까지.
@property (nonatomic) BOOL requiresExclusiveTouchType API_AVAILABLE(ios(9.2)); // 기본값은 YES입니다.
// 다른 제스처 인식기와의 관계를 생성합니다. 이 관계는 다른 제스처 인식기가 UIGestureRecognizerStateFailed로 전환될 때까지 이 제스처의 액션을 호출하지 않도록합니다.
// 만약 다른 제스처 인식기가 UIGestureRecognizerStateRecognized 또는 UIGestureRecognizerStateBegan으로 전환되면 대신 이 인식기는 UIGestureRecognizerStateFailed로 전환됩니다.
// 예시: 단일 탭이 더블 탭이 실패할 때까지 기다릴 수 있습니다.

(void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;
// 개별 UIGestureRecognizer 하위 클래스는 하위 클래스 별 위치 정보를 제공할 수 있습니다. 세부 정보는 각 하위 클래스를 참조하십시오.

(CGPoint)locationInView:(nullable UIView*)view; 
// 일반적인 단일 지점의 위치 정보입니다. 일반적으로 관련된 터치들의 중심점입니다.
@property(nonatomic, readonly) NSUInteger numberOfTouches; 
// 위치 정보를 요청할 수 있는 터치의 수

(CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view; 
// 특정 터치의 위치 정보입니다.
@property (nullable, nonatomic, copy) NSString *name API_AVAILABLE(ios(11.0), tvos(11.0)); 
// 디버깅을 위해 로깅에 표시될 이름입니다.

// 처리된 마지막 이벤트에서의 값입니다.
// 이 값들은 제스처를 위한 요구 사항으로 간주되지 않습니다.
@property (nonatomic, readonly) UIKeyModifierFlags modifierFlags API_AVAILABLE(ios(13.4)) API_UNAVAILABLE(tvos, watchos);
@property (nonatomic, readonly) UIEventButtonMask buttonMask API_AVAILABLE(ios(13.4)) API_UNAVAILABLE(tvos, watchos);
@end
//@end 는 Objective-C에서 클래스 구현 섹션을 종료하는 키워드입니다.
@protocol UIGestureRecognizerDelegate <NSObject>
@optional
// 제스처 인식기가 UIGestureRecognizerStatePossible에서 전환을 시도할 때 호출됩니다. NO를 반환하면 UIGestureRecognizerStateFailed로 전환됩니다.
* (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
// 다른 제스처 인식기에 의해 gestureRecognizer 또는 otherGestureRecognizer 중 하나의 인식이 차단될 때 호출됩니다.
// 두 개의 제스처가 동시에 인식되도록하려면 YES를 반환하십시오. 기본 구현은 NO를 반환합니다(기본적으로 두 가지 제스처는 동시에 인식될 수 없습니다).
//
// 참고: YES를 반환하면 동시 인식이 보장됩니다. NO를 반환하면 동시 인식을 방지할 수 없습니다. 다른 제스처의 대리인이 YES를 반환할 수 있기 때문입니다.
* (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
// 인식을 시도할 때마다 한 번 호출되므로, 인식기 간에 뷰 계층 구조를 통해 실패 요구 사항을 설정할 수 있습니다.
// gestureRecognizer와 otherGestureRecognizer 사이에 동적 실패 요구 사항을 설정하려면 YES를 반환하십시오.
//
// 참고: YES를 반환하면 실패 요구 사항이 설정됩니다. NO를 반환하면 다른 제스처의 대리자 또는 하위 클래스 메서드가 YES를 반환할 수 있기 때문에 실패 요구 사항이 없다는 것을 보장하지 않습니다.
* (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer API_AVAILABLE(ios(7.0));
* (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer API_AVAILABLE(ios(7.0));
// 새로운 터치에 대해 touchesBegan:withEvent:가 제스처 인식기에 호출되기 전에 호출됩니다. 이 터치를 인식기에서 볼 수 없도록하려면 NO를 반환하십시오.
* (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
// 새로운 프레스에 대해 pressesBegan:withEvent:가 제스처 인식기에 호출되기 전에 호출됩니다. 이 프레스를 인식기에서 볼 수 없도록하려면 NO를 반환하십시오.
* (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceivePress:(UIPress *)press;
// -gestureRecognizer:shouldReceiveTouch: 또는 -gestureRecognizer:shouldReceivePress: 중 하나가 호출되기 전에 한 번 호출됩니다.
// 이 이벤트를 인식기에서 볼 수 없도록하려면 NO를 반환하십시오.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveEvent:(UIEvent *)event API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos);

@end

NS_HEADER_AUDIT_END(nullability, sendability)

#else
#import <UIKitCore/UIGestureRecognizer.h>
#endif

UIGestureRecognizerDelegate 프로토콜을 정의하는 코드입니다. 이 프로토콜은 사용자 제스처 인식을 위한 도구인 UIGestureRecognizer 객체의 동작을 커스터마이징할 수 있도록 해줍니다.

gestureRecognizerShouldBegin: 메서드는 제스처 인식기가 UIGestureRecognizerStatePossible 상태에서 벗어나려 할 때 호출됩니다. 이 메서드를 구현하여 NO를 반환하면 해당 제스처 인식기는 UIGestureRecognizerStateFailed로 전환됩니다.

gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: 메서드는 두 개의 제스처 인식기가 동시에 인식될 때 호출됩니다. 이 메서드를 구현하여 YES를 반환하면 두 개의 제스처 인식기가 동시에 인식됩니다.

gestureRecognizer:shouldRequireFailureOfGestureRecognizer:와 gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer: 메서드는 각각 한 제스처 인식기가 다른 제스처 인식기보다 우선 순위가 높을 때 호출됩니다. 이 메서드를 구현하여 YES를 반환하면 높은 우선 순위의 제스처 인식기가 먼저 인식되며, NO를 반환하면 낮은 우선 순위의 제스처 인식기가 먼저 인식됩니다.

shouldReceiveTouch:와 shouldReceivePress: 메서드는 제스처 인식기가 새로운 터치나 프레스 이벤트를 인식하기 전에 호출됩니다. 이 메서드를 구현하여 NO를 반환하면 해당 이벤트를 인식하지 않습니다.

마지막으로 gestureRecognizer:shouldReceiveEvent: 메서드는 iOS 13.4 이상에서 추가된 메서드로, 제스처 인식기가 이벤트를 인식하기 전에 호출됩니다. 이 메서드를 구현하여 NO를 반환하면 해당 이벤트를 인식하지 않습니다.

728x90
반응형
LIST

'iOS' 카테고리의 다른 글

iOS 터치-4  (0) 2023.04.16
iOS 터치-3  (0) 2023.04.16
iOS 터치-1  (0) 2023.04.16
iOS 계층구조-4  (0) 2023.04.15
iOS 계층구조-3  (0) 2023.04.15