Ch 4. 앱 개발 숙련 주차 과제
⎮ 포켓몬 연락처 앱 만들기
- Lv.1
- 캡처된 모습과 같게 UI 를 구현합니다.
UILabel, UITableView, UIButton 을 이용해서 기본적인 UI 를 구성합니다.
UITableViewCell 에는 프로필 이미지를 보여줄 UIImageView 와 이름을 보여줄 UILabel 을 넣습니다.
전화번호를 표시할 UILabel 도 넣습니다.
프로필 이미지는 원모양이 되도록 합니다.
“추가” 버튼을 우상단에 위치 시킵니다.
Cell 의 높이는 80으로 지정합니다.
* 원의 테두리는 layer.borderColor, layer.borderWidth 개념을 사용하면 구현할 수 있습니다.
캡처된 화면은 임의의(더미) dataSource 를 끼워넣어 UI 를 확인한 모습입니다.
- 내가 작성한 코드
// ViewController.swift
class ViewController: UIViewController {
// UILabel 생성
private let label: UILabel = {
let label = UILabel()
label.text = "친구 목록"
label.textColor = .black
label.font = .boldSystemFont(ofSize: 30)
label.textAlignment = .center
return label
}()
// button이 탭되었을 때, self를 작성하려면 lazy var로 선언되어 있어야함
private lazy var button: UIButton = {
let button = UIButton()
button.setTitle("추가", for: .normal)
button.setTitleColor(.gray, for: .normal)
button.backgroundColor = .white
// button.addTarget(self, action: <#T##Selector#>, for: <#T##UIControl.Event#>)
return button
}()
// TableView 생성
private let tableView: UITableView = {
let tableView = UITableView()
// register로 셀을 등록해줘야 셀이 화면에 표시됨
tableView.register(TableViewCell.self, forCellReuseIdentifier: TableViewCell.id)
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
//tableView의 delegate와 dataSource가 VC임을 명시해야함
tableView.delegate = self
tableView.dataSource = self
}
func configureUI() {
view.backgroundColor = .white
[label, button, tableView].forEach { view.addSubview($0) }
label.snp.makeConstraints {
$0.top.equalToSuperview().offset(70)
$0.centerX.equalToSuperview()
}
button.snp.makeConstraints {
$0.centerY.equalTo(label.snp.centerY)
$0.trailing.equalToSuperview().offset(-20)
}
tableView.snp.makeConstraints {
$0.centerX.equalToSuperview()
$0.top.equalTo(label.snp.bottom).offset(40)
$0.bottom.equalToSuperview().offset(-50)
$0.leading.trailing.equalToSuperview().inset(30)
}
}
}
// TableView의 Delegate
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
80
}
}
// TableView의 DataSource
extension ViewController: UITableViewDataSource {
// 셀을 return하려면 셀을 만들어야 함
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// 여기서 재사용이 가능한 셀을 만들어줌
guard let cell = tableView.dequeueReusableCell(withIdentifier: TableViewCell.id) as? TableViewCell else { return UITableViewCell() }
return cell
}
// 섹션 안에 있는 행의 개수
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
7
}
}
// TableViewCell.swift
class TableViewCell: UITableViewCell {
// 이게 셀을 식별하는 고유 ID, 나중에 재사용할 때 어떤 셀인지 넣어줘야 함
static let id = "TableViewCell"
let nameLabel: UILabel = {
let label = UILabel()
label.text = "name"
label.textColor = .black
label.font = .systemFont(ofSize: 14)
return label
}()
let phoneNumberLabel: UILabel = {
let label = UILabel()
label.text = "010-0000-0000"
label.textColor = .black
label.font = .systemFont(ofSize: 14)
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
configureUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configureUI() {
let imageView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "")
imageView.contentMode = .scaleAspectFit
imageView.layer.cornerRadius = 30
imageView.layer.borderWidth = 1
return imageView
}()
// 셀 안에 view를 반영할 때는 contentView에 반영해주면 됨
[imageView, nameLabel, phoneNumberLabel].forEach { contentView.addSubview($0) }
imageView.snp.makeConstraints {
$0.centerY.equalTo(contentView.snp.centerY)
$0.width.height.equalTo(60)
$0.leading.equalTo(contentView.snp.leading).offset(20)
}
nameLabel.snp.makeConstraints {
$0.centerY.equalTo(imageView.snp.centerY)
$0.leading.equalTo(imageView.snp.trailing).offset(20)
}
phoneNumberLabel.snp.makeConstraints {
$0.centerY.equalTo(imageView.snp.centerY)
$0.trailing.equalTo(contentView.snp.trailing).offset(-20)
}
}
}
⎮ UITableView
https://developer.apple.com/documentation/uikit/uitableview
UITableView | Apple Developer Documentation
A view that presents data using rows in a single column.
developer.apple.com
테이블뷰는 위의 사진과 같이 반복되는 행을 표현할 때 효과적이다
테이블뷰의 각각의 행에는 cell이라는 객체가 존재하고,
그 객체를 세팅해서 테이블 위에 얹을 수 있다.
TableView를 사용하려고 할 때, 반드시 알아야하는 개념은
TableViewCell, TableViewDataSource, TableViewDelegate이다
- TableViewCell
https://developer.apple.com/documentation/uikit/uitableviewcell
UITableViewCell | Apple Developer Documentation
The visual representation of a single row in a table view.
developer.apple.com
TableViewCell은 테이블뷰에서 단일 행을 나타내는 시각적인 부분이다.
다음의 그림에서 볼 수 있듯 TableViewCell은 Content 영역(ContentView)을 가지고 있으며,
해당 영역을 커스터마이징할 수 있다.
첫번째 그림에서처럼 셀에 선택 영역이나 강조 색상을 적용하게 할 수 있고,
두번째 그림에서처럼 보조 뷰(Detail 등)를 추가할 수도 있다.
세번째 그림에서처럼 셀을 삭제하는 등의 편집이 가능한 상태로 만들 수도 있다.
- TableVieDelegate
https://developer.apple.com/documentation/uikit/uitableviewdelegate
UITableViewDelegate | Apple Developer Documentation
Methods for managing selections, configuring section headers and footers, deleting and reordering cells, and performing other actions in a table view.
developer.apple.com
TableViewDelegate의 내부에도 다양한 기능이 있지만, 그 중 가장 기본적으로 사용되는 기능은
행의 높이를 정해주는 기능이다.
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
70
}
}
위의 코드처럼 높이를 설정해줄 수 있는데,
앞서 설명한 것들과 마찬가지로 행의 높이를 지정해줘야 TableView를 이상 없이 구현할 수 있다.
- TableViewDataSource
테이블뷰 셀의 ContentView에 무언가를 채워넣었다고 끝나는 것이 아니다.
테이블뷰 설정을 위해서는 UITableViewDataSource 프로토콜을 채택하고,
필수 메서드를 구현해줘야 한다.
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as? TableViewCell else {
return UITableViewCell()
}
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
7
}
}
numberOfRowsInSection은 섹션에 행을 몇개 설정할 것인지,
cellForRowAt은 행에 표시할 셀이 무엇인지 세팅하는 것이다.
여기서 중요한 것이 cell을 식별하는 Identifier이다.
Identifier를 통해 어떤 클래스의 TableViewCell을 적용할 것인지 식별할 수 있기 때문에,
해당 부분을 누락(혹은 잘못 작성)하면 원하는 데이터를 전달하지 못하는 경우가 있기 때문에 주의하도록 하자.
⎮ UITableView에 데이터 채우기
https://developer.apple.com/documentation/uikit/filling-a-table-with-data
Filling a table with data | Apple Developer Documentation
Create and configure cells for your table dynamically using a data source object, or provide them statically from your storyboard.
developer.apple.com
'스파르타코딩 클럽 > 개인과제' 카테고리의 다른 글
24. 스파르타 코딩클럽 [본캠프 - 포켓몬 연락처앱 (3)] (0) | 2025.04.20 |
---|---|
23. 스파르타 코딩클럽 [본캠프 - 포켓몬 연락처앱 (2)] (0) | 2025.04.20 |
21. 스파르타 코딩클럽 [본캠프 - 계산기 앱 : 정수기 최종] (0) | 2025.04.03 |
20. 스파르타 코딩클럽 [본캠프 - 계산기 앱 : 정수기(10)] (0) | 2025.04.03 |
19. 스파르타 코딩클럽 [본캠프 - 계산기 앱 : 정수기(9)] (0) | 2025.04.02 |