iOS에서 터치가 일어나면, 우선 캐패시티브 터치스크린을 통해 위치와 크기 등의 정보가 기기로 넘어가고 기기에서 UIGestureRecognizer.h 이란 헤드 파일에서 이 정보를 읽고 내용 새로 만들어진 메소드 인스턴스에 저장하게 되는 줄 알았지만, chatGPT한테 아니라고 혼났다.
아니란다... 그래서 UIResponder를 공부하기로...
예제코드
이 코드에서 직접적으로 UIResponder 클래스를 상속받은 클래스는 없습니다. 하지만 UIView 클래스는 UIResponder 클래스를 상속받고 있으며, 따라서 MyView 클래스는 UIView 클래스의 서브클래스이면서 UIResponder 클래스의 서브클래스입니다. 따라서 MyView 클래스는 터치 이벤트에 응답하기 위해 UIResponder의 메서드를 오버라이드하고 있습니다.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let myView = MyView(frame: CGRect(x: 100, y: 100, width: 200, height: 200))
view.addSubview(myView)
}
}
class MyView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
// 이 뷰가 유저 인터랙션을 받을 수 있도록 설정
isUserInteractionEnabled = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
// 터치가 시작될 때 처리할 코드 작성
print("Touches began")
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
// 터치가 움직일 때 처리할 코드 작성
print("Touches moved")
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
// 터치가 끝날 때 처리할 코드 작성
print("Touches ended")
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event)
// 터치가 취소될 때 처리할 코드 작성
print("Touches cancelled")
}
}
Set<UITouch> 를 보고 Set<Element> 구조체 부터 공부하기로 🥹 하ㅏㅏㅏ...
@frozen public struct Set<Element> where Element : Hashable {
/// 지정된 요소 수에 대한 미리 할당된 공간이 있는 빈 집합을 생성합니다.
///
/// 이 초기화 메서드를 사용하면 생성 후 집합에 삽입할 요소 수를 미리 알고 있는 경우 집합의 저장소 버퍼의 중간 재할당을 방지할 수 있습니다.
///
/// - Parameter minimumCapacity: 생성된 집합이 저장소 버퍼를 재할당하지 않고 저장할 수 있는 최소 요소 수입니다.
*** 여기에서 frozen이란? ***
Swift 프로그래밍 언어에서의 frozen 키워드는 데이터 구조체나 열거형의 변경 불가능성(immutable)을 명시하는 역할을 합니다.
frozen이라는 단어 자체는 "얼어붙은, 얼린" 등의 의미를 가지며, Swift 언어에서도 이와 유사한 의미로 사용됩니다. 데이터의 변경이 금지되어 그 값을 읽기 전용으로 만들어서, 마치 얼어붙은 것처럼 고정된 데이터 구조체를 생성하는 것을 목적으로 합니다.(이야 다 생각이 있구나?)
@available(iOS 2.0, *)
@MainActor open class UITouch : NSObject {
open var timestamp: TimeInterval { get }
open var phase: UITouch.Phase { get }
open var tapCount: Int { get } // touch down within a certain point within a certain amount of time
@available(iOS 9.0, *)
open var type: UITouch.TouchType { get }
// majorRadius and majorRadiusTolerance are in points
// The majorRadius will be accurate +/- the majorRadiusTolerance
@available(iOS 8.0, *)
open var majorRadius: CGFloat { get }
@available(iOS 8.0, *)
open var majorRadiusTolerance: CGFloat { get }
open var window: UIWindow? { get }
open var view: UIView? { get }
@available(iOS 3.2, *)
open var gestureRecognizers: [UIGestureRecognizer]? { get }
open func location(in view: UIView?) -> CGPoint
open func previousLocation(in view: UIView?) -> CGPoint
// Use these methods to gain additional precision that may be available from touches.
// Do not use precise locations for hit testing. A touch may hit test inside a view, yet have a precise location that lies just outside.
@available(iOS 9.1, *)
open func preciseLocation(in view: UIView?) -> CGPoint
@available(iOS 9.1, *)
open func precisePreviousLocation(in view: UIView?) -> CGPoint
// Force of the touch, where 1.0 represents the force of an average touch
@available(iOS 9.0, *)
open var force: CGFloat { get }
// Maximum possible force with this input mechanism
@available(iOS 9.0, *)
open var maximumPossibleForce: CGFloat { get }
// Azimuth angle. Valid only for stylus touch types. Zero radians points along the positive X axis.
// Passing a nil for the view parameter will return the azimuth relative to the touch's window.
@available(iOS 9.1, *)
open func azimuthAngle(in view: UIView?) -> CGFloat
// A unit vector that points in the direction of the azimuth angle. Valid only for stylus touch types.
// Passing nil for the view parameter will return a unit vector relative to the touch's window.
@available(iOS 9.1, *)
open func azimuthUnitVector(in view: UIView?) -> CGVector
// Altitude angle. Valid only for stylus touch types.
// Zero radians indicates that the stylus is parallel to the screen surface,
// while M_PI/2 radians indicates that it is normal to the screen surface.
@available(iOS 9.1, *)
open var altitudeAngle: CGFloat { get }
// An index which allows you to correlate updates with the original touch.
// Is only guaranteed non-nil if this UITouch expects or is an update.
@available(iOS 9.1, *)
open var estimationUpdateIndex: NSNumber? { get }
// A set of properties that has estimated values
// Only denoting properties that are currently estimated
@available(iOS 9.1, *)
open var estimatedProperties: UITouch.Properties { get }
// A set of properties that expect to have incoming updates in the future.
// If no updates are expected for an estimated property the current value is our final estimate.
// This happens e.g. for azimuth/altitude values when entering from the edges
@available(iOS 9.1, *)
open var estimatedPropertiesExpectingUpdates: UITouch.Properties { get }
}
UITouch 클래스는 화면에 터치가 발생할 때마다 생성되며, 터치 이벤트의 정보를 담고 있습니다. 이 클래스를 통해 터치의 위치, 터치의 상태, 터치의 세부 정보 등을 확인할 수 있습니다.
*** 여기에서 MainActor란? ***
@MainActor 속성은 Swift 5.5부터 추가된 새로운 속성 중 하나입니다. 이 속성은 동시성 관련 문제를 방지하기 위해 새롭게 도입된 Swift Concurrency(스위프트 동시성) 기능에서 사용됩니다.
"Main Actor"는 iOS, macOS 및 tvOS와 같은 애플 플랫폼에서 사용되는 주 스레드를 나타냅니다. 이 스레드는 UI 업데이트 및 사용자 상호 작용과 같은 중요한 작업을 처리하는 데 사용됩니다. @MainActor 속성은 이러한 중요한 작업이 "Main Actor"에서 실행되도록 보장하고, 다른 스레드에서의 동시성 문제를 방지하기 위해 사용됩니다.
'iOS' 카테고리의 다른 글
Feature, ViewModel, UseCase (0) | 2023.04.20 |
---|---|
iOS 터치-4 (0) | 2023.04.16 |
iOS 터치-2 (0) | 2023.04.16 |
iOS 터치-1 (0) | 2023.04.16 |
iOS 계층구조-4 (0) | 2023.04.15 |