Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 클린 코드
- Xcode
- ios
- ribs
- clean architecture
- uitableview
- map
- 리펙터링
- swift documentation
- 리펙토링
- UITextView
- Clean Code
- swiftUI
- MVVM
- Refactoring
- combine
- UICollectionView
- rxswift
- collectionview
- 스위프트
- 애니메이션
- Human interface guide
- Observable
- tableView
- HIG
- RxCocoa
- Protocol
- SWIFT
- 리팩토링
- uiscrollview
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] CADisplayLink 사용 방법 (디스플레이 주사율, 타이머, RunLoop.Mode) 본문
iOS 응용 (swift)
[iOS - swift] CADisplayLink 사용 방법 (디스플레이 주사율, 타이머, RunLoop.Mode)
jake-kim 2023. 5. 23. 00:03CADisplayLink 개념
- 디스플레이의 주사율에 맞춰서, 특정 함수를 호출시킬 수 있는 타이머 개체
- 보통 타이머는 시간에 따라 호출되지만, CADisplayLink는 디스플레이 프레임(frame) 기준으로 발생하는 타이머
- 디스플레이의 갱신 주기에 맞춰서 특정 코드를 실행하도록 예약하는것
- 사용처) 애니메이션 및 그래픽 렌더링에 동기화하여 작업을 수행할 때 사용
- CADisplayLink
- 화면 갱신 주기와 관련된 작업을 수행하는데 사용되므로, 디스플레이와 연결(link)를 제공한다는 의미
CADisplayLink 사용방법
* 예제 시작 코드
import UIKit
class ViewController: UIViewController {
private let button: UIButton = {
let button = UIButton()
button.setTitle("button", for: .normal)
button.setTitleColor(.systemBlue, for: .normal)
button.setTitleColor(.blue, for: .highlighted)
button.addTarget(self, action: #selector(tap), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(button)
NSLayoutConstraint.activate([
button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
])
}
@objc private func tap() {
startDisplayLink()
}
}
- displayLink 선언
private var displayLink: CADisplayLink?
- 버튼을 탭했을 때 DisplayLink 실행
- CADisplayLink(target:selector:)로 초기화
- preferredFramesPerSecond을 10으로 설정하면 초당 콜백이 10번 호출
@objc private func tap() {
startDisplayLink()
}
private func startDisplayLink() {
stopDisplayLink()
displayLink = CADisplayLink(target: self, selector: #selector(update))
displayLink?.preferredFramesPerSecond = 10
displayLink?.add(to: .main, forMode: .default)
}
@objc private func update() {
print("frame", view.frame)
}
private func stopDisplayLink() {
displayLink?.invalidate()
displayLink = nil
}
displayLink?.add(to: .main, forMode: .default) 파라미터인 RunLoop와 RunLoop.Mode 개념
- RunLoop
- 이벤트 처리, 타이머, 소켓 통신 등 애플리케이션의 이벤트 루프를 관리하는 객체
- RunLoop는 스레드에 바인딩되어 해당 스레드의 이벤트 처리를 담당
- (메인 스레드에는 기본적으로 메인 RunLoop가 생성)
- RunLoop.Mode
- RunLoop의 모드를 식별하기 위한 값
- .default: 대부분의 애니메이션 및 사용자 이벤트 처리 작업이 이 모드에서 수행
- .common: default와 유사하지만 조금 더 낮은 우선순위
- .tracking: 스크롤 뷰와 같은 추적 작업을 수행할 때 사용되는 모드 (default보다 더 높은 우선순위)
- .modal: 모달 작업 수행할 때 사용되는 모드
- .eventTracking: 사용자 이벤트 트래킹을 위해 사용되는 모드 (터치 이벤트를 처리하는데 사용)
타임아웃 처리
- CADisplayLink는 무한히 실행될 수 있으므로 DispatchWorkItem를 사용하여 타임아웃처리도 추가
private func startDisplayLink() {
stopDisplayLink()
displayLink = CADisplayLink(target: self, selector: #selector(update))
displayLink?.preferredFramesPerSecond = 10
displayLink?.add(to: .main, forMode: .default)
let workItem = DispatchWorkItem(block: { [weak self] in
self?.stopDisplayLink()
})
dispatchWorkItem = workItem
DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: workItem)
}
@objc private func update() {
print("frame", view.frame)
}
private func stopDisplayLink() {
displayLink?.invalidate()
displayLink = nil
dispatchWorkItem?.cancel()
}
주의사항
- displaylink는 강한 참조를 이루기 때문에, 명시적으로 invalidate()를 호출해주지 않으면 메모리 해제가 되지 않음
* 전체코드: https://github.com/JK0369/ExCADisplayLink
* 참고
https://developer.apple.com/documentation/foundation/runloop/mode
https://developer.apple.com/documentation/quartzcore/cadisplaylink/1621323-add
'iOS 응용 (swift)' 카테고리의 다른 글
Comments