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 |
Tags
- Xcode
- combine
- Observable
- 리펙터링
- uitableview
- tableView
- UICollectionView
- RxCocoa
- map
- HIG
- collectionview
- 리펙토링
- UITextView
- swift documentation
- 애니메이션
- rxswift
- ios
- 스위프트
- SWIFT
- Protocol
- Clean Code
- 리팩토링
- 클린 코드
- Human interface guide
- Refactoring
- ribs
- uiscrollview
- swiftUI
- clean architecture
- MVVM
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] UIControl의 UIButton 액션 클로저 만드는 방법 (touchUpInside, UIControl.Event, objc_setAssociatedObject) 본문
iOS 응용 (swift)
[iOS - swift] UIControl의 UIButton 액션 클로저 만드는 방법 (touchUpInside, UIControl.Event, objc_setAssociatedObject)
jake-kim 2023. 1. 6. 23:36일반적인 UIButton의 action 처리 방법
- UIButton의 인스턴스 메소드인 addTarge(_:action:for:)를 사용하여 처리
- 단점은 button의 addTarget하는 부분에서 특정 지역변수에 대한 기능을 touchUpInside 액션 시 동작하게 하기 어려운 점이 존재
- 아래 abc 지역 프로퍼티를 button의 touchUpInside될 때 출력하고 싶어도 어려운 상태
- button의 클로저로 만들면? (아래에서 계속)
class ViewController: UIViewController {
private let button = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
let abc = 123
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("타이틀", for: .normal)
button.setTitleColor(.systemBlue, for: .normal)
button.setTitleColor(.blue, for: .highlighted)
view.addSubview(button)
NSLayoutConstraint.activate([
button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
])
button.addTarget(self, action: #selector(tab), for: .touchUpInside)
}
@objc private func tab() {
print("Tab Button!")
}
}
UIControl.Event에 대한 클로저 만드는 방법
* (방법은 해당 글 참고하여 작성)
- 사용하는 쪽 - 클로저로 접근 가능
// 적용 전
button.addTarget(self, action: #selector(tab), for: .touchUpInside)
// 적용 후
button.addAction {
print("Tab Button!", abc)
}
- 구현 방법
- UIControl에 extension으로 정의
- 파리미터로 controlEvents와 closure를 받는 메소드
public extension UIControl {
func addAction(for controlEvents: UIControl.Event = .touchUpInside, _ closure: @escaping () -> ()) {
}
}
- 클로저를 처리하는 @objc class를 따로 정의하고, 이 클로저를 넘겨주도록 구현
- 끝에 objc_setAssociatedObject를 사용하여 해당 액션 클로저가 해제되지 않도록 retain 걸어놓기
- objc_setAssociatedObject 관련 개념은 이전 포스팅 글 참고
func addAction(for controlEvents: UIControl.Event = .touchUpInside, _ closure: @escaping () -> ()) {
@objc class ClosureSleeve: NSObject {
let closure: () -> ()
init(_ closure: @escaping () -> ()) {
self.closure = closure
}
@objc func invoke() {
closure()
}
}
let sleeve = ClosureSleeve(closure)
addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
objc_setAssociatedObject(self, "\(UUID())", sleeve, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
* 전체 코드: https://github.com/JK0369/ExAction
* 참고
https://stackoverflow.com/questions/25919472/adding-a-closure-as-target-to-a-uibutton
'iOS 응용 (swift)' 카테고리의 다른 글
Comments