[iOS] UITableView + UITableViewCell (2): ์ปค์คํ ํ ์ด๋ธ ๋ทฐ ์ปจํธ๋กค๋ฌ์ Data Source์ ์ ์ฒด
Dynamic UITableView
์ง๋ ํฌ์คํธ์์๋ ์ฝ๋๋ ํ ์ค๋ ์์ฑํ์ง ์๊ณ ๊ธฐ๋ณธ์ ์ธ ํ ์ด๋ธ ๋ทฐ์ ๊ตฌ์ฑ์์๋ค๊ณผ ๋ฐ์ดํฐ๋ฅผ ์ด๋ค ์์ผ๋ก ์ถ๊ฐํ ์ ์๋์ง ์ ๋ฆฌํด๋ณด์์ต๋๋ค. ์์์ ์ผ๋ก ์ ์ ํ๋ํ๋ ๋ง๋ค์ด์ฃผ๋ค ๋ณด๋ ์๊ฐ๋ ์ค๋ ๊ฑธ๋ฆฌ๊ณ ์ค์ ๊ฐ๋ฐ์์๋ ์ฌ์ฉํ๊ธฐ ์ด๋ ต๋ค๋ ๋๋์ ๋ฐ์๋๋ฐ์, ๊ทธ๋์ ์ค๋์ UITableViewController๋ฅผ ์ปค์คํ ์ผ๋ก ๋ง๋ค์ด ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค!
Custom UITableViewController
๋จผ์ ์ปค์คํ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํ UItableViewController ํ์ผ์ ๋ง๋ค์ด์ฃผ๊ฒ ์ต๋๋ค!
์๋ก ๋ง๋ค๊ธฐ์์ Cocoa Touch Class๋ฅผ ์ ํํ ๋ค์,
ํ ์ด๋ธ ๋ทฐ ์ปจํธ๋กค๋ฌ๋ฅผ ์ ํํด ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
์ถ๊ฐ๊ฐ ์๋ฃ๋๋ฉด ๋ค์ ์คํ ๋ฆฌ๋ณด๋๋ก ๋์๊ฐ์ ์์ฑํ ํ ์ด๋ธ ๋ทฐ ์ปจํธ๋กค๋ฌ์ ํด๋์ค๋ฅผ ์ฐ๊ฒฐํด์ฃผ๋ฉด ์ถ๊ฐ๊ฐ ์๋ฃ๋ฉ๋๋ค!
์ฝ๋๋ฅผ ํ ๋ฒ ์ด์ด๋ด ์๋ค!
์ด๋ ๊ฒ ๊ธฐ๋ณธ์ ์ธ ์ฝ๋์ ์ฃผ์์ฒ๋ฆฌ๋ ์ฝ๋๋ค์ด ๋ณด์ผ ํ ๋ฐ์, override ๋ ๋ ๋ฉ์๋๋ ๋ฐ๋์ ๊ตฌํ๋์ด์ผ ํ๋ ์ฝ๋์ด๊ธฐ ๋๋ฌธ์ ์ด๋ ๊ฒ ๋์์๊ฒ ์ฃ ? MARK๋ฅผ ์ฝ์ด๋ณด๋ฉด ํ ์ด๋ธ ๋ทฐ์ data source์ ๊ด๋ จ๋ ๋ด์ฉ์ธ ๊ฒ ๊ฐ์ผ๋ ๋จผ์ data source๊ฐ ๋ฌด์์ธ์ง ์ฐพ์๋ด ์๋ค!!
UITableViewDataSource: Data Source์ ์ ์ฒด
๐ก The methods that an object adopts to manage data and provide cells for a table view.
์ ํ ๊ณต์๋ฌธ์์์๋ ํ ์ด๋ธ ๋ทฐ ๋ฐ์ดํฐ ์์ค๋ฅผ ์ด๋ ๊ฒ ์ ์ํ๊ณ ์์ต๋๋ค! ๊ฐ์ฒด๊ฐ ํ ์ด๋ธ ๋ทฐ์ ๋ฐ์ดํฐํฐ๋ฅผ ๊ด๋ฆฌํ๊ณ ํ ์ด๋ธ ๋ทฐ์ ์ ์ ์ ๊ณตํด์ฃผ๊ธฐ ์ํด ์ฑํํ ์ ์๋ ๋ฉ์๋๋ค์ ์งํฉ์ด๋ผ๊ณ ํ๋ค์. ์์ง ์ ์๋ฟ์ง ์์์ ๋ ์์ธํ ์ค๋ช ์ ์ฝ์ด๋ณด์์ต๋๋ค.
๐กTable views manage only the presentation of their data; they do not manage the data itself. To manage the data, you provide the table with a data source object—that is, an object that implements the
UITableViewDataSource protocol. A data source object responds to data-related requests from the table.
ํ ์ด๋ธ ๋ทฐ๋ ๋ฐ์ดํฐ๋ฅผ ๋ณด์ฌ์ฃผ๋ ์ญํ ๋ง์ ์ํํ๊ณ , ๋ฐ์ดํฐ๋ฅผ ์ง์ ๊ด๋ฆฌํ์ง๋ ์๋๋ค๊ณ ํฉ๋๋ค. ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด์๋ Data source ๊ฐ์ฒด๋ฅผ ํ ์ด๋ธ ๋ทฐ์ ์ ๊ณตํด์ผ ํ๊ณ ์ด ๊ฐ์ฒด๋ UITableViewDataSource ํ๋กํ ์ฝ์ ์ฑํํ์ฌ ๊ตฌํํ ๊ฐ์ฒด๋ผ๊ณ ํ๋ค์. ๊ทธ๋ฆฌ๊ณ ํ ์ด๋ธ์ ๋ฐ์ดํฐ์ ๊ด๋ จ๋ ์์ ์ ์์ฒญ์ด ๋ค์ด์ค๋ฉด ๊ทธ ์์ฒญ์ ์๋ตํ๋ ๊ฒ ์ญ์ data source ๊ฐ์ฒด์ ๋๋ค.
๐ก It also manages the table's data directly, or coordinates with other parts of your app to manage that data. Other responsibilities of the data source object include:
- Reporting the number of sections and rows in the table.
- Providing cells for each row of the table.
- Providing titles for section headers and footers.
- Configuring the table's index, if any.
- Responding to user- or table-initiated updates that require changes to the underlying data.
data source ๊ฐ์ฒด๊ฐ ํ๋ ์ผ์ ์ด๋ ์ต๋๋ค!
- ์น์ ์ ๊ฐ์์ ํ์ ๊ฐ์๋ฅผ ํ ์ด๋ธ์ ์๋ ค์ฃผ๊ธฐ
- ๊ฐ ํ์ ๋ํ ์ ์ ํ ์ด๋ธ์๊ฒ ์ ๊ณตํ๊ธฐ
- ์น์ ์ ํค๋์ ํธํฐ๋ฅผ ์ ๊ณตํ๊ธฐ
- ํ ์ด๋ธ์ ์ธ๋ฑ์ค๋ฅผ ์์๋ด๊ธฐ
- ํ ์ด๋ธ์์ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋์์ ๋ ๋ฐ์ํ๊ธฐ
์ด์ ์ข ๊ฐ์ด ์ค์๋์? MVC ๋ชจ๋ธ์ด ์ต์ํ๋ค๋ฉด Data source๋ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๋ Model์ ์ญํ ์ ํ๋ค๊ณ ์๊ฐํ๋ฉด ๋๊ฒ ๋ค์!
ํ ์ด๋ธ ๋ทฐ์๊ฒ ์ ๋ณด๋ฅผ ์๋ ค์ฃผ์
๊ทธ๋ผ ๋ค์ ์๊น์ ์ฝ๋๋ก ๋์๊ฐ๋ณด๊ฒ ์ต๋๋ค.
Data Source ๊ฐ์ฒด๊ฐ ํ๋ ์ผ ์ค์ ์น์ ์ ๊ฐ์์ ํ์ ๊ฐ์๋ฅผ ์๋ ค์ฃผ๋ ์ผ์ด ์์๋๋ฐ์, ๋ฐ๋์ ๊ตฌํํด์ผ ํ๋ ๋ ๋ฉ์๋๊ฐ ๋ฐ๋ก ๊ทธ ์ญํ ์ ํ๋ ๋ฉ์๋์ ๋๋ค! ๊ทธ๋ผ ๋์ ์ผ๋ก ํ๊ณผ ์น์ ์ ์ค์ ํ๊ธฐ ์ํด์ ์ฝ๋๋ฅผ ์กฐ๊ธ ์์ฑํด๋ณผ๊ฒ์.
struct CallInfo {
let name: String
let type: String
let day: String
let randomNames = ["๋ฏผ์ค", "์์ค", "์์ค", "๋์ค", "์์ฐ", "์ฃผ์", "ํ์ค", "์งํธ", "์งํ", "์ค์", "์ค์ฐ", "ํ์ฐ", "๋ํ", "์งํ", "๊ฑด์ฐ", "์ฐ์ง", "์ ์ฐ", "์์ง", "๋ฏผ์ฌ", "ํ์ค", "์ฐ์ฐ", "์ ์ค", "์ ์ฐ", "์น์ฐ", "์นํ", "์์ค", "์คํ", "์์ฐ", "์งํ", "์น๋ฏผ", "์ง์ฐ", "์ ์ฐฌ", "์ค์ฐ", "๋ฏผ์ฑ", "์ค์", "์ํ", "์ง์ฐ", "์ง์", "์์ฐ", "์์ค", "์ง์ฐ", "์ํ", "๋ฏผ์", "ํ์", "ํ์ค", "์ค์", "์ง์ ", "์ง๋ฏผ", "์ฑ์", "์ง์ค", "์์", "์์", "๋ค์", "์์", "์ง์", "์๋น", "์์จ", "์๋ฆฐ", "์์", "์ง์", "์์ค", "์ง์", "ํ๋ฆฐ", "์์", "์ ์ง", "์ฑ์"]
let randomTypes = ["ํด๋์ ํ", "๋ํ๋ฏผ๊ตญ"]
let randomDays = ["์ค๋", "์ด์ ", "๊ธ์์ผ", "๋ชฉ์์ผ", "์์์ผ", "ํ์์ผ", "์์์ผ"]
init() {
self.name = self.randomNames.shuffled().first!
self.type = self.randomTypes.shuffled().first!
self.day = self.randomDays.shuffled().first!
}
}
class TableViewController: UITableViewController {
var sectionA: [CallInfo] = []
var sectionB: [CallInfo] = []
override func viewDidLoad() {
super.viewDidLoad()
(0..<100).forEach { _ in
sectionA.append(CallInfo())
sectionB.append(CallInfo())
}
}
.
.
.
์ผ๋จ ์ด์ ํฌ์คํธ์์ ๋ง๋ค์๋ ์ต๊ทผ ํตํ ๋ชฉ๋ก์ ๋ง๋ค๊ธฐ ์ํด์ ์๋ฃ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๊ณ ๋ทฐ๊ฐ ์์๋ ๋ 100๊ฐ์ ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ ๊ฐ์ ์น์ ์ ๋ฃ์ด์ฃผ๋๋ก ํ์ต๋๋ค.
๊ทธ๋ผ ์ด์ ์ค๋ฒ๋ผ์ด๋ ๋์ด ์๋ data source ๋ฉ์๋๋ฅผ ๊ตฌํํ ์ ์๊ฒ ์ฃ ?
class TableViewController: UITableViewController {
var sectionA: [CallInfo] = []
var sectionB: [CallInfo] = []
var sections: [[CallInfo]] = []
override func viewDidLoad() {
super.viewDidLoad()
(0...100).forEach { _ in
sectionA.append(CallInfo())
sectionB.append(CallInfo())
}
sections = [sectionA, sectionB]
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return sectionA.count
case 1:
return sectionB.count
default:
return 0
}
}
.
.
.
numberOfSections์ ๋ฐํ ๊ฐ์ผ๋ก๋ ์น์ ์ ๊ฐ์๋ฅผ ๋ฐํํ๋๋ก ํด ์ฃผ๊ณ , numberOfRowsInSection๋ ๊ฐ ์น์ ์ ์์ดํ ๊ฐ์๋ฅผ ๋ฐํํ๋๋ก ํ์ต๋๋ค.
์ด๋๋ก ์คํํด๋ณผ๊น์?
์๋ฌ๊ฐ ๋ฉ๋๋ค.. ์๋ฌ๋ฅผ ์ฝ์ด๋ณด๋ฉด,
UITableView dataSource returned a nil cell for row at index path:~~~
๋ผ๊ณ ํ๋๋ฐ์, ์๊น Data Source๊ฐ ํ๋ ์ผ ์ค์ ํ ์ด๋ธ์ ๊ฐ ํ์ ํด๋นํ๋ ์ ์ ์ ๊ณตํ๋ค๋ ๋ด์ฉ์ด ์์๋ ๊ฒ์ ๊ธฐ์ตํ์๋์? ํ ์ด๋ธ ๋ทฐ๊ฐ UITableDataSource์๊ฒ ์น์ ์ ๊ฐ์์ ํ์ ๊ฐ์๋ฅผ ๋ฌผ์ด๋ดค๊ธฐ ๋๋ฌธ์ ํด๋น ์ ๋ณด๋ฅผ ์๋ ค์ฃผ์์ง๋ง ๊ฐ ํ์ ์ด๋ค ๋ด์ฉ์ ํ์ํ ์ง ์๋ ค์ฃผ์ง ์์๊ธฐ ๋๋ฌธ์ ๋๋ค! ํ ์ด๋ธ ๋ทฐ๋ ์ ๋ฌ๋ฐ์ ๊ฐ์๋๋ก ํ ์ด๋ธ์ ์ ์ ํ์ํ๋ ค๊ณ ํ์ง๋ง ํ์ํ๋ ค๋ index path์ ๋ํ ์ ์ data source์๊ฒ ๋ฐ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฒ์ ๋๋ค.
์ ์ ๋๊ฒจ์ฃผ๋ ๋ฐฉ๋ฒ์ ์์๋ณด๊ธฐ ์ ์ ์์ํ ๋จ์ด์ธ index path๋ถํฐ ์ ๋ฆฌํ๊ฒ ์ต๋๋ค! index path๋ ์ ์๊ฐ ๋ ๊ฐ ๋ค์ด๊ฐ ์๋ ๋ฐฐ์ด์ ๊ฐ์ง๋ 2์ฐจ์ ๋ฐฐ์ด์ธ๋ฐ์, ๊ฐ ํ์ ๋ํ ์ ๋ณด๋ฅผ [์น์ ์ธ๋ฑ์ค, ํ ์ธ๋ฑ์ค]๋ก ๊ด๋ฆฌํฉ๋๋ค.
์ด๋ ๊ฒ ๋ง์ด์ฃ .
๊ทธ๋ผ ์ด์ ์ ์ ๋ง๋ค์ด์ ํ ์ด๋ธ ๋ทฐ์ ์ ๋ฌํด๋ด ์๋ค!
์ ์ ํ ์ด๋ธ ๋ทฐ์ ๋๊ฒจ์ฃผ๊ธฐ ์ํด์๋ UITableViewDataSource์ ์๋ ๋ฉ์๋๋ฅผ ํ๋ ๋ ๊ตฌํํ๋ฉด ๋๊ฒ ์ต๋๋ค!
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
}
tableView ๋ฉ์๋๋ค ์ค์์ ์ธ์๋ก cellForRowAt์ ๊ฐ์ง๋ ๋ฉ์๋๋ฅผ ์ ํํ๊ณ ๊ตฌํํฉ๋๋ค. ๋ฆฌํด ๊ฐ์ผ๋ก UITableCell์ ๊ฐ์ง๊ณ ์๋ค์. ์ด๋ ์ ์ ๋ง๋ค๊ธฐ ์ํด ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ํจํด์ด dequeueResusableCell ๋ฉ์๋๋ฅผ ์ด์ฉํ๋ ๊ฒ์ธ๋ฐ์. ํ๋ฒ ์ฌ์ฉํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๋จผ์ ์คํ ๋ฆฌ๋ณด๋๋ก ์ด๋ํด์ ํ ์ด๋ธ ๋ทฐ๋ฅผ ์ ํํ ํ์ ์ฐ์ธก ๋ด๋น๊ฒ์ดํฐ์ Content ์ต์ ์ Dynamic Prototype์ผ๋ก ๋ณ๊ฒฝํด์ค๋๋ค. ๊ทธ๋ฆฌ๊ณ prototype cell์ ํ๋ ์ฌ์ฉํ๋ ๊ฒ์ผ๋ก ์ค์ ํ ๊ฒ์.
์ด์ ๋ง๋ค์ด์ง ํ ์ด๋ธ ๋ทฐ ์ ์ ์ ํํ๊ณ identifier๋ฅผ ์ถ๊ฐํด์ค๋๋ค. ๊ฐ๋จํ๊ฒ "cell"์ด๋ผ๊ณ ์ ๋ ์ค์ ํ ๊ฒ์.
์ด์ ๋ค์ ์ฝ๋๋ก ๋์์์ dequeueResusableCell ๋ฉ์๋๋ก ์ ์ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
return cell
}
์ด๋ ๊ฒ withIndentifier ์ธ์์ ์คํ ๋ฆฌ๋ณด๋์์ ์ค์ ํ identifier๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ์ ์ด ์์ฑ๋ฉ๋๋ค. cellForRowAt ๋ฉ์๋๋ ์ฐ๋ฆฌ๊ฐ Data Source๋ฅผ ํตํด ํ ์ด๋ธ ๋ทฐ์ ์๋ ค์ฃผ์๋ ํ์ ๊ฐ์๋งํผ ์คํ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํ์ฌ ์ด๋ค ํ์ ๋ํ ์ ์ ๋ฐ๊ธฐ๋ฅผ ์ํ๋์ง indexPath ์ธ์๋ฅผ ํตํด ์๋ ค์ค๋๋ค. indexPath๋ฅผ ์ถ๋ ฅํด๋ณด๋ฉด ํ์คํ๊ฒ ์ ์ ์์ฃ .
๊ทธ๋ฐ๋ฐ ๋ญ๊ฐ ์ด์ํฉ๋๋ค.. ์ฒ์๋ถํฐ ๋ชจ๋ ์ ์ index path๊ฐ ๋ถ๋ ค์ง๋ ๊ฒ์ด ์๋๋ผ ์คํฌ๋กค์ ํ ๋๋ง๋ค index path๊ฐ ์ ๋ฐ์ดํธ๋ฉ๋๋ค. ์ ์ด๋ด๊น์? ์๋ง๋ dequeueResusableCell ๋ฉ์๋์ ์ด๋ฆ์ ๋ณด๋ฉด์ ์ dequeue๊ฐ ์์๊น.. ์ resusable ์ผ๊น..๋ผ๋ ๊ถ๊ธ์ฆ์ด ๋ค์ง ์์ผ์ จ๋์?? dequeueResusableCell์ ์ ์ฒด์ ๋ํด์๋ ๋ค์ ํฌ์คํธ์์ ์์๋ณด๊ธฐ๋ก ํ๊ณ ์ผ๋จ์ cellForRowAt ๋ฉ์๋๋ก ๋ง๋ค์ด์ง ์ ์ ์ฐ๋ฆฌ๊ฐ ๊ฐ์ง๊ณ ์๋ ์ ๋ณด๋ฅผ ๋ฃ์ด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
ContentConfiguration: ์ ์ ๊พธ๋ฉฐ๋ณด์
์ปค์คํ ์ ์ ๋ง๋ค๊ฑฐ๋ ์๋ก์ด ๋ทฐ๋ฅผ ๋ง๋ค์ด์ ์ ์ ์ถ๊ฐํด์ฃผ๋ ๊ฒ์ผ๋ก ์ ์ ๋ด์ฉ์ ์ฑ์ธ ์๋ ์์ง๋ง, ContentConfiguration์ ํตํด์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํด์ฃผ๋ ์คํ์ผ๋ก ์์ ์ ํ ์๋ ์์ต๋๋ค. ContentConfiguration์ iOS 14๋ถํฐ ์ค์ ํ๋ ๋ฐฉ์์ด ๋ณ๊ฒฝ๋์๋ค๊ณ ํ๋ค์.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
var config = cell.defaultContentConfiguration()
config.text = sections[indexPath.section][indexPath.item].name
config.secondaryText = sections[indexPath.section][indexPath.item].type
config.secondaryTextProperties.color = UIColor.darkGray
cell.accessoryType = .detailButton
cell.contentConfiguration = config
return cell
}
์ฝ๋๋ ์๊ฐ๋ณด๋ค ๋จ์ํฉ๋๋ค! ๋จผ์ dequeueReusableCell๋ก ๋ง๋ ์ ์ด ๊ฐ์ง๊ณ ์๋ defaultContentConfiguration์ ์ธ์คํด์ค๋ฅผ ์์ฑํฉ๋๋ค.
var config = cell.defaultContentConfiguration()
๊ทธ๋ฆฌ๊ณ cellForRowAt์ ์ธ์๋ก ์ ๋ฌ๋๋ indexPath๋ฅผ ์ด์ฉํด์ ์ฐ๋ฆฌ๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ฐ์ดํฐ๋ค์ ๊ฐ์ ธ์ต๋๋ค. indexPath.section์ผ๋ก ์น์ ์ธ๋ฑ์ค๋ฅผ ์ป์ ์ ์๊ณ , indexPath.item์ผ๋ก ํ์ ์ธ๋ฑ์ค๋ฅผ ์ป์ ์ ์์ต๋๋ค. Data Source์ ์ฒ์ ์ ๋ฌํ๋ ์น์ ์ ๊ฐ์์ ์น์ ๋น ํ์ ๊ฐ์๊ฐ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ณ ์์ผ๋ indexPath๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ ํ์ ์ผ์นํ๋ ๋ฐ์ดํฐ๋ฅผ ์ป์ ์ ์๊ฒ ์ฃ ?
callInfo ์ธ์คํด์ค๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ฐ์ดํฐ์ค ์ด๋ฆ์ text๋ก ์ค์ ํ๊ณ , secondary text๋ก๋ type ์ ๋ณด๋ฅผ ๋ณด์ฌ์ฃผ๋๋ก ํ๊ฒ ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ secondary text๋ ์ฐ๋ฝ์ฒ ์ฑ์ ๋์์๋ ๊ฒ์ฒ๋ผ ํ์ ์์์ผ๋ก ๋ณ๊ฒฝํด์ฃผ์์ต๋๋ค!
config.text = sections[indexPath.section][indexPath.item].name
config.secondaryText = sections[indexPath.section][indexPath.item].type
config.secondaryTextProperties.color = UIColor.darkGray
์ ๋ณด๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ฒํผ์ธ AccessoryView๋ ๋ฃ์ด์ผ๊ฒ ์ฃ ? ์ด์ ํฌ์คํธ์์๋ ์คํ ๋ฆฌ๋ณด๋์์ ํ๋ ๊ฒ์ฒ๋ผ Detail๋ก ์ค์ ํ๊ฒ ์ต๋๋ค.
cell.accessoryType = .detailButton
๋ง์ง๋ง์ผ๋ก ์ด ์ธ์คํด์ค๋ฅผ ์ด ํ์ ๋ฃ์ ์ ์ ContentConfiguration์ผ๋ก ์ง์ ํ๊ณ ์ ์ ๋ฐํํ๋ฉด ์ ์ด ์์ฑ๋ฉ๋๋ค!
cell.contentConfiguration = config
return cell
์คํ!
์ํ๋ ๋๋ก ํ ์ด๋ธ ๋ทฐ๊ฐ ์์ฑ๋์์ต๋๋ค..!
๋ง์ง๋ง์ผ๋ก ์น์ ์ด๋ฆ์ ํ์ํด์ค๊ฒ์. ์ด์ ํฌ์คํธ์์๋ ์คํ ๋ฆฌ๋ณด๋์์ ์น์ ์ header๋ฅผ ์ค์ ํด์ฃผ์๋๋ฐ์, ์ด๋ฒ์๋ ํ ์ด๋ธ ๋ทฐ์ ๋ฉ์๋๋ค ์ค titleForHeaderInSection๋ฅผ ์ค๋ฒ๋ผ์ด๋ ํด์ ์น์ ์ธ๋ฑ์ค์ ๋ง๋ ์ ๋ชฉ์ ๋ฐํํด์ฃผ๋๋ก ํ๊ฒ ์ต๋๋ค.
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0:
return "A"
case 1:
return "B"
default:
return nil
}
}
์คํํ ๊ฒ์~!
์ด๋ฒ์๋ ์น์ ์ด๋ฆ๊น์ง ์ ํ์๋ฉ๋๋ค~!
์ด๋ ๊ฒ ํด์ UITableViewController๋ฅผ ์์ํ๋ ์ปค์คํ ํด๋์ค๋ฅผ ๋ง๋ค์ด์ ํ ์ด๋ธ ๋ทฐ๋ฅผ ๋ง๋ค์ด๋ดค์ต๋๋ค! ์์ง ์ปค์คํ ์ ์ ๋ง๋ค์ด๋ณด์ง ์์๋๋ฐ์, ๋ค์ ํฌ์คํธ์์๋ dequeueResusableCell์ ๋ํ ์ด์ผ๊ธฐ๋ฅผ ๋จผ์ ํ๊ณ ์ปค์คํ ์ ์ ๋ง๋ค์ด ํ ์ด๋ธ ๋ทฐ์์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค~!