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
- 스위프트
- UITextView
- ribs
- swift documentation
- map
- 클린 코드
- RxCocoa
- 리펙토링
- MVVM
- 애니메이션
- ios
- Clean Code
- swiftUI
- Observable
- uiscrollview
- 리펙터링
- clean architecture
- UICollectionView
- SWIFT
- 리팩토링
- combine
- HIG
- Refactoring
- uitableview
- tableView
- collectionview
- rxswift
- Human interface guide
- Protocol
- Xcode
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] UITableView 셀 터치 애니메이션 넣는 방법 (#프로토콜 활용하기, 추상화) 본문
iOS 응용 (swift)
[iOS - swift] UITableView 셀 터치 애니메이션 넣는 방법 (#프로토콜 활용하기, 추상화)
jake-kim 2024. 7. 17. 01:07셀이 탭 되었을때 애니메이션 넣는 방법
- 터치 이벤트는 tableView의 Delegate 메서드인 didSelectRowAt에서 받을 수 있는데, 여기서 특정 셀을 캐스팅해서 터치 애니메이션 실행이 가능
- (애니메이션은 셀이 탭 되었을때 셀이 가지고 있는 메서드를 실행시키고, 셀 안에서 UIView.animate로 애니메이션처리)
- (애니메이션 적용은 쉽기 때문에 이 포스팅 글에서는 생략)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as? CustomCellType1
cell?.didTapCell()
}
- 하지만 이렇게하면 확장성이 없는 문제가 존재
- 만약 CutstomCellType2라는 셀이 생겼을 때도 똑같이 캐스팅해주어야함
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? CustomCellType1 {
cell?.didTapCell()
} else if let cell = tableView.cellForRow(at: indexPath) as? CustomCellType2 {
cell?.didTapCell()
}
}
프로토콜을 활용하여 좋은 코드 만들기
- 프로토콜에는 여러가지 기능이 있지만, 그 중에서 딱 필요한 기능만 추상화할 수 있는 기능이 존재
- 만약 "셀이 탭 된다"는 것을 하나의 기능으로 생각하고 프로토콜로 먼저 정의한다면, 추상화 되었기 때문에 어떤 셀이든 사용이 가능
protocol CellTouchable {
func didTapCell()
}
- 이것을 더 넘어서 Cell 뿐만이 아닌 View로 더욱 추상화시켜서 view에도 적용이 가능
protocol Touchable {
func didTap()
}
- 이렇게 하면 사용하는 쪽에서도 일일이 캐스팅 필요 없이, 한줄로 표현이 가능
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
(tableView.cellForRow(at: indexPath) as? Touchable)?.didTap()
}
* 전체 코드
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let tableView = UITableView()
let data = ["Type 1", "Type 2", "Type 1", "Type 2", "Type 1"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.frame = self.view.bounds
tableView.dataSource = self
tableView.delegate = self
self.view.addSubview(tableView)
tableView.register(CustomCellType1.self, forCellReuseIdentifier: CustomCellType1.reuseIdentifier)
tableView.register(CustomCellType2.self, forCellReuseIdentifier: CustomCellType2.reuseIdentifier)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = data[indexPath.row]
if item == "Type 1" {
let cell = tableView.dequeueReusableCell(withIdentifier: CustomCellType1.reuseIdentifier, for: indexPath) as! CustomCellType1
cell.label.text = "Type 1 cell"
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: CustomCellType2.reuseIdentifier, for: indexPath) as! CustomCellType2
cell.button.setTitle("Type 2 cell", for: .normal)
return cell
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// before
// if let cell = tableView.cellForRow(at: indexPath) as? CustomCellType1 {
// cell?.didtapCell()
// } else if let cell = tableView.cellForRow(at: indexPath) as? CustomCellType2 {
// cell?.didtapCell()
// }
// after
(tableView.cellForRow(at: indexPath) as? Touchable)?.didTap()
}
}
protocol Touchable {
func didTap()
}
class CustomCellType1: UITableViewCell, Touchable {
static let reuseIdentifier = "CustomCellType1"
override var isHighlighted: Bool {
didSet { print("test>", isHighlighted) }
}
override var isSelected: Bool {
didSet { print("test>>", isSelected) }
}
let label: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(label)
NSLayoutConstraint.activate([
label.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16)
])
}
func didTap() {
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class CustomCellType2: UITableViewCell, Touchable {
static let reuseIdentifier = "CustomCellType2"
let button: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Press me", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(button)
NSLayoutConstraint.activate([
button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
button.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16)
])
}
func didTap() {
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
'iOS 응용 (swift)' 카테고리의 다른 글
[iOS - swift] Optional 타입에 map 사용하기(Synthetic Sugar) (0) | 2024.07.24 |
---|---|
[iOS - swift] 그라데이션 (gradient, gradation, CAGradientLayer) 주는 방법 (0) | 2024.07.22 |
[iOS - swift] 스크롤 될 때 headerView 색상 변경 방법 (3) | 2024.07.15 |
[iOS - swift] 문자열 합치는 방법 (joined vs reduce) (0) | 2024.07.12 |
[iOS - swift] overlay 주는 방법, 색상 섞는 방법, 뷰 위에 딤드효과 주는 방법 (compositingFilter, screenBlendMode) (0) | 2024.07.10 |
Comments