[WWDC 19] Advances in UI Data Sources
KEY POINT! (์์ฝ)
Diffabla DataSource์ ๋ฑ์ฅ
UICollectionView, UITableView์ ์ ์ฉ์ด ๊ฐ๋ฅํ๋ค. (iOS13)
snapshot์ด๋ผ๋ ์๋ก์ด ๊ฐ๋ ์ด ๋ฑ์ฅํ๋ฉด์, performBatchUpdates๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์ด์ก๋ค.
Diffable DataSource์ ์ฌ์ฉ ๋ฐฉ๋ฒ
NSDiffableDataSource๋ฅผ ์์ฑํ๋ค.
Hashable Protocol์ ์ฑํํ ์๋ณ์๋ฅผ ์ถ๊ฐํ๋ค.
snapshot์ ์ ์ฉํ๋ค.
๋ณ๊ฒฝ๋ ๋ถ๋ถ์ Diffable DataSource๊ฐ ์๋์ผ๋ก ์ฒ๋ฆฌํด์ ์์ฐ์ค๋ฌ์ด ์ ๋๋ฉ์ด์ ์ ์ ์ฉํ๋ค.
WWDC ์์ ๋ชฉ์ฐจ
ํ์ฌ CollectionView์ TableView์์ ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ๊ด๋ฆฌํ๊ณ ์๋๊ฐ?
์๋ก์ด Data ๊ด๋ฆฌ ๋ฐฉ๋ฒ
์ฑ์ ํตํ ๋ฐ๋ชจ
Diffable DataSource๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ
ํ์ฌ CollectionView์ TableView์์ ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ๊ด๋ฆฌํ๊ณ ์๋๊ฐ?
๊ฐ๋ฐํ ๋ TableView, CollectionView๋ ์ ๋ง ๋นผ๋์ ์ ์๋ค. ์ด๋ค ์ฑ์ด๋ , ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ๋ฐํด์ผํ๋ ์น๊ตฌ๋ค ๊ฐ๋ค. (์ ํ์์๋ Collection View๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ค๋ช ํ์ง๋ง, ๋๋ Table View ๊ธฐ๋ฐ์ผ๋ก ์ค๋ช ํ๊ณ ์ดํดํ ์์ ์ด๋ค)
UITableView DataSource
TableView๋ฅผ ๊ตฌํํ ๋, ์ฐ๋ฆฌ๋ UITableViewDataSource
๋ผ๋ ํ๋กํ ์ฝ์ ์ฑํํ๊ฒ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ํ๋กํ ์ฝ์ ํญ์ ์๋ค๋ค์ ๊ตฌํํด์ค์ผ๋๋ค.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// ๋ช ๊ฐ์ Cell์ ๋ณด์ฌ์ค๊ฑฐ์ผ?
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// ์ด๋ค Cell์ ๋ณด์ฌ์ค๊ฑฐ์ผ?
}
๊ต์ฅํ ์ง๊ด์ ์ด๋ค. ๋ช ๊ฐ์ Cell์, ์ด๋ค ๋ชจ์์ผ๋ก ๋ณด์ฌ์ค ์ง ์๋ ค์ฃผ๊ธฐ๋ง ํ๋ฉด, TableView๋ฅผ ๋ง๋ค ์ ์๋ค.
์ค์ ์ฑ์์ ์ด๋ป๊ฒ ์ฌ์ฉํ๊ณ ์๋๊ฐ?
๋ค์์ ๋ด๊ฐ ์งํํ๊ณ ์๋ ํ๋ก์ ํธ ShortcutsZip์ด๋ค.(์๋ SwiftUI์)
๋จ์ถ์ด(Shortcut์ด๋ผ๋ ๊ตฌ์กฐ์ฒด)๋ค์ ๋ค์ํ ํํ๋ก ๋ถ๋ฅํด์, ์ฌ์ฉ์๋ค์ด ๋ ์ฝ๊ฒ ๋จ์ถ์ด๋ฅผ ์ฐพ์ ์ ์๋๋ก ๊ตฌ์ฑ ๋ผ ์๋ค.
์ด๋ ๊ฒ ๋ค์ํ ์ ๋ณด๋ฅผ, ๋๋ ๊ฐ์ ๋ฐ์ดํฐ ํ์
์ด์ง๋ง ํน์ ์นดํ
๊ณ ๋ฆฌ๋ก ๋๋ ์ ์ ๋ณด๋ฅผ ์ ๊ณตํ๊ณ ์ถ์ ๋ ์ฐ๋ฆฌ๋ Section
์ด๋ผ๋ ๊ฐ๋
์ DataSource์๊ฒ ์ ๊ณตํด์ค์ผํ๋ค.
func numberOfSections(in tableView: UITableView) -> Int {
// ๋ช ๊ฐ์ Section์ ๊ฐ์ง๊ณ ์์ด?
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// ์น์
๋ง๋ค ๋ฐ์ดํฐ๊ฐ ๋ช ๊ฐ ๋ค์ด์์ด?
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Cell์ ๋ชจ์์ ์ด๋ป๊ฒ ์๊น?
}
๋ด๊ฐ ์งํํ๋ ShortcutsZip์ ๊ฒฝ์ฐ, ์ด๋ฐ์์ผ๋ก ํํ์ ํ ์ ์๋ค.
var shortcutDataList = [[Shortcut]]()
/* ์๋ต */
func numberOfSections(in tableView: UITableView) -> Int {
shortcutDataList.count // 2์ฐจ์ ๋ฐฐ์ด์ count ๊ฐ์ด Section์ ๊ฐ์
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
shortcutDataList[section].count // ๋ฐฐ์ด์ section ์ธ๋ฑ์ค์ ๋ค์ด์๋ ๋ฐ์ดํฐ์ ๊ฐ์๊ฐ Cell์ ๊ฐ์
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Section๋ง๋ค Cell ๋ชจ์์ ์ง์ ํด์ ๋ฆฌํด
let section = indexPath.section
switch section {
let cell = UITableViewCell()
return cell
}
}
๊ทธ๋ฐ๋ฐ, ์ฐ๋ฆฌ๊ฐ ์ค์ ๋ก ๊ฐ๋ฐํ ๋ 1์ฐจ์ ๋ฐฐ์ด๋ก ํํํ๊ธฐ ์ด๋ ค์ด ๊ฒฝ์ฐ๊ฐ ๊ต์ฅํ ๋ง๋ค. ๋ฌด์ ์ฌ ์ฑ์ ๋ด ๋ณด์. (ํ ์ด๋ธ ๋ทฐ๋ ์๋)
ShortcutsZip๊ณผ ๋ค๋ฅด๊ฒ, ๋ฉ์ธํ๋ฉด์์ ๋ค์ํ ์ ๋ณด๋ฅผ ๋ณด์ฌ์ฃผ๊ณ ์๋ค. ๊ฐ ์น์ ๋ง๋ค Clothes๋ผ๋ Struct๊ฐ ์๋๋ผ, ๊ด๊ณ , ์นดํ ๋ก๊ธฐ, ๋ผ์ด๋ธ ํธ์ฑํ, ์ท ๋ฑ ๋ค์ํ Struct๋ก ๊ตฌ์ฑ๋ ์ ๋ณด๋ค์ ๋ณด์ฌ์ฃผ๊ณ ์๋ค.
๊ทธ๋ฐ๋ฐ, ๋ฌด์ ์ฌ์ ๊ฐ์ด ์ฌ๋ฌ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ DataSource์ ์ด๋ป๊ฒ ํํํ๊ฒ ๋ ๊น๋ฅผ ์๊ฐํด๋ณด์. (์ผ์ฐจ์์ ์ผ๋ก๋ง) ๋์ถฉ ์ด๋ ๊ฒ ์๊ฒผ๊ฒ ์ง??
var advertiseList: [AdverTise] = [] // ๊ด๊ณ ํญ
var categories: [Category] = [] // ์นดํ
๊ณ ๋ฆฌ ๋ฆฌ์คํธ
var liveContents: [Contents] = [] // ๋ผ์ด๋ธ ๋ฐฉ์ก
/* ๊ธฐํ ์ ๋ณด๋ค .. */
/* (์๋ต)์๋ฒ ๋ฐ์ดํฐ ํธ์ถ -> ๊ฐ ์ ๋ณด๋ค ์
๋ฐ์ดํธํ๋ ๋ก์ง๋ค */
func numberOfSections(in tableView: UITableView) -> Int {
// section์ ๊ฐ์ return
// ์น์
๊ฐ์๋ฅผ ์ง์ ๋ฆฌํดํ๊ฑฐ๋ UI๋ฅผ ์๋ฒ๋ก ๊ฒฐ์ ํ๋ฉด ๊ทธ ๋ฐ์ดํฐ์ count๋ฅผ return)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return advertiseList.count
case 1:
return categories.count
case 2:
return liveContents.count
/* ์๋ต */
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let section = indexPath.section
switch section {
let cell = UITableViewCell()
return cell
}
}
์์ง๊น์ง dataSource๋ ๊ต์ฅํ ์ง๊ด์ ์ด๋ค. ๋ด๊ฐ ๊ฐ์ง Section ๊ฐ์, Section ๋ด๋ถ ๋ฐ์ดํฐ ๊ฐ์, Cell์ ๋ชจ์๋ง ์๋ ค์ค๋ค๋ฉด, ์์์ TableView๋ฅผ ๊ทธ๋ฆด ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋ผ ์ด๋ค ๋ฌธ์ ๊ฐ ์๋๋ฐ?
์ฐ์ ์ค์ ์ฑ์ ๋จ์ํ 1~2์ฐจ์์ ๋ฐฐ์ด๋ก ํํํ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค.
์ฌ๊ธฐ์ ๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ ์ฌ์ฉ์์ ์ ๋ ฅ์ผ๋ก ๋ฐ์ดํฐ๊ฐ ๋ณํํ์ ๋, ๊ฐ๋ฐ์๊ฐ ์ง์ UI์๋ ์ ๋ฐ์ดํธ๋ฅผ ์์ผ์ค์ผํ๋ค๋ ๊ฒ์ด๋ค. (๋ฐ์ดํฐ๊ฐ ๋ณํํ๋ค๊ณ , ์์์ TableView๊ฐ ๋ณํ์ง ์๋๋ค. ์ฐ๋ฆฌ๋
reloadData
๋ฑ์ ์ฌ์ฉํด์ผํ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.)
์กฐ๊ธ ๋ ์์ธํ ์๋ก ๋ฌด์ ์ฌ ์ฑ์์ ์ด๋ค ์ท์ ์ข์์๋ฅผ ๋๋ฅธ ์ํฉ์ ์๊ฐํด๋ณด์. ๊ทธ๋ผ ๋์ถฉ ์ด๋ฐ ๋ก์ง์ผ๋ก ๋์ ํ ๊ฒ์ด๋ค.ใ
์ฌ์ฉ์๊ฐ ์ข์์ ๋ฒํผ์ ๋๋ฅธ๋ค.
์๋ฒ์ Post๋ฅผ ๋ณด๋ (ใ ใ ๊ฐ ์ข์์ ๋๋ ์ด)
์๋ฒ๊ฐ ์๋ต์ ๋ณด๋ด์ค
์๋ต์ ๊ธฐ๋ฐ์ผ๋ก ๋ฐ์ดํฐ์ UI ์ ๋ฐ์ดํธํ๋ค.
์ฐ๋ฆฌ๋ ์ด๋, ์์ฐ์ค๋ฌ์ด ์ ๋๋ฉ์ด์ ์ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด์ reloadData()๋ฅผ ์ํํ ํ์ scroll์ ์์น๋ฅผ ๋ฐ๊ฟ์ฃผ๊ธฐ๋ ํ๊ณ , insertRow(at:)์ ํตํด์ ๋ฐ์ดํฐ์ ๋ณํ์ UI์ ๋ณํ๋ฅผ ์ฐ๊ฒฐ์์ผ์ฃผ๊ธฐ๋ ํ๋ค. ์ฆ, ์ด์ ๊น์ง ํ๋ ์์ ๋ค์ด ๊ฐ๋ฐ์๋ค์ด ์ง์ ๋ณ๊ฒฝ๋ ๋ฐ์ดํฐ์ ์์น๋ฅผ ์ฐพ์์! ์ ๋๋ฉ์ด์ ์ ๋ณด์ฌ์คฌ๋ค๋ ๊ฒ์ด๋ค. (๋ง๊ฒ ์ง?)
๊ทธ๋ฆฌ๊ณ ๊ฐ์ฅ ํฌ๋ฆฌํฐ์ปฌํ ๋ฌธ์ ! ๊ฐ๋ฐํ๋ ์ค, synchronization์๋ฌ๋ฅผ ๋ง์ด ๊ฒฝํํ์ ๊ฒ์ด๋ค. ๊ฐ๋จํ ์์๋ก, Section์ด 3๊ฐ์ธ TableView๊ฐ ์๋ค๊ณ ๊ฐ์ ํ์. ์ด๋, 3๋ฒ์งธ Section์ ๋ฐ์ดํฐ๊ฐ 1๊ฐ ์์๋๋ฐ ๋ง์ง๋ง ๋จ์ ๋ฐ์ดํฐ ํ๋๋ฅผ ์ง์ด ๊ฒ์ด๋ค. ๊ทธ๋ผ Section์๋ ์๋ฌด๊ฒ๋ ์๊ฒ ๋๋ค. ์ด๋, ๋๊ฐ dataSource์์ ์๋ ค์ค ๊ฐ์ด๋, ๋ด๊ฐ ๋ณด์ฌ์ค์ผ๋๋ ๊ฐ์ด ๋ค๋ฅธ๋ฐ? ์ด๋ฌ๋ฉด์ ์ฑ์ด ์ฃฝ๊ฒ ๋๋๊ฒ์ด๋ค ^^^^
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: Invalid update: invalid number of sections. The number of sections contained in the collection view after the update (10) must be equal to the number of sections contained in the collection view before the update (10), plus or minus the number of sections inserted or
deleted (0 inserted, 1 deleted).'
์ ํ์ ์ด๋ ๊ฒ ์์ฐ์ค๋ฌ์ด ์ ๋๋ฉ์ด์ ์ ๋ณด์ฌ์ฃผ๋๊ฒ ์ด๋ ค์ด ์ํฉ, ๊ทธ๋ฆฌ๊ณ synchronization ์๋ฌ ๋ฑ์ด dataSource์ ์๋ค๊ณ ๋งํ๋ค. ์ฆ, UI๋ฅผ ์ ๋ฐ์ดํธํ๋ ์ฃผ์ฒด = Data! ๊ทธ๋ฐ๋ฐ, Data๊ฐ ๋ณํํด๋ ๊ฐ๋ฐ์๊ฐ ์๋ ค์ฃผ์ง ์์ผ๋ฉด, UI๊ฐ ์ ๋ฐ์ดํธ ๋์ง ์๋ ์ด๊ฒ๋ค์ด ๋ชจ์ฌ ์ ๋ฐ ๋ฌธ์ ๋ฅผ ๋ฐ์์ํจ๋ค๋ ๊ฒ์ด๋ค.
๊ทธ๋์ ๋ฐ์ดํฐ๊ฐ ์
๋ฐ์ดํธ ๋๋ฉด, UI๋ฅผ ์
๋ฐ์ดํธ ์ํค๋ฉด ๋์ง ์์๊น? ์์ ํ์ํ ๊ฒ์ด ๋ฐ๋ก Diffable DataSource์ธ ๊ฒ์ด๋ค~!!!~!
์๋ก์ด Data ๊ด๋ฆฌ ๋ฐฉ๋ฒ - Diffable Data Source
Diffable Data Source์ ๊ธฐ๋ณธ์ ์ธ ๊ฐ๋ ์ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ์ตํด ๋์๋ค๊ฐ, ๋ณ๊ฒฝ์ฌํญ์ด ์์ผ๋ฉด, UI๋ฅผ ์ ๋ฐ์ดํธ ์ํค๋ ๊ฒ์ด๋ค. ์ฆ, ๋ฐ์ดํฐ์ ๊ด๋ฆฌ์ UI ์ ๋ฐ์ดํธ๋ฅผ ๋ถ๋ฆฌ์ํค์ง ์๊ฒ ๋ค๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด, ์ด์ ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ๊ธฐ์ตํ ๊น? โ ์ฌ๊ธฐ์ ๋ํ๋๋ ๊ฐ๋
์ด snapshot
์ด๋ค.
์ฐ๋ฆฌ๊ฐ snapshot()
์ด๋ผ๋ ํจ์๋ฅผ ํธ์ถํ๋ ๊ทธ ์๊ฐ, DataSource์ ์ ์ฅ๋์ด์๋ ๋ฐ์ดํฐ๋ค์ commit ํ๋ค. ๊ทธ๋ค์ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋ ํ ๋ค์ ํ ๋ฒ snapshot()์ ํธ์ถํ๊ฒ ๋๋ฉด, ์ด์ snapshot๊ณผ ๋น๊ตํด์ ์ด๋ค ๋ฐ์ดํฐ๊ฐ ๋ฌ๋ผ์ก๋์ง ํ์
ํ๊ณ ๊ทธ๊ฒ์ ์ ๋๋ฉ์ด์
์ผ๋ก ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด๋ค. (option์ ์ด์ฉํด์ ์ ๋๋ฉ์ด์
์ ๋ ์ ์๋ค)
dataSource๋ ๋ฐ์ดํฐ์ ๋ณ๊ฒฝ์ฌํญ์ ์ด๋ป๊ฒ ์ธ์งํ ์ ์์๊น? โ ์ด๋ฅผ ์ํด ์ฐ๋ฆฌ๋ Item์ ๋ฐ๋์ Hashable ํ๋กํ ์ฝ์ ์ฑํํด์ค์ผํ๋ค. ์ฆ, Diffable Data Source๋ ์ด์ ๋ฐ์ดํฐ๋ค์ ID๋ฅผ ๊ธฐ์ตํด๋๊ณ , ๊ทธ ๊ฐ๋ค์ด ๋ณํ๋ฉด ๋ฐ์ดํฐ๊ฐ ๋ณํ์์ ์ธ์ํ ์ ์๋ค๋ ๊ฒ์ด๋ค!
์ด์ ์ฐ๋ฆฌ๋ performBatchUpdates
์์ด ๋ชจ๋ ๋ณ๊ฒฝ์ฌํญ์ ๋ํ ์ฑ
์์ DataSource์๊ฒ ์์ํ๊ฒ ๋์๋ค. ๊ทธ๋ฆฌ๊ณ DiffableDataSource๋ ์์ฃผ ์์ฐ์ค๋ฝ๊ณ ์์ Animation์ ๋ณด์ฌ์ฃผ๊ฒ ๋๋ค.
DiffableDataSource๋ UITableView, UICollectionView ๋ชจ๋ ์ง์ํ๋ฉฐ, Mac, TVOS, iOS๋ฅผ ์ง์ํ๋ค. (iOS 13๋ถํฐ ๊ฐ๋ฅ)
์ฑ์ ํตํ ๋ฐ๋ชจ (์ฌ์ฉ ๋ฐฉ๋ฒ)
๐ก ๋ด ๋ง์๋๋ก ์ค๋ช ํ ๊ฑฐ์.. WWDC ์์ ๋ณด๋ ๊ฑฐ ์ถ์ถด ๐ก
์์ฝํ์๋ฉด ์ธ ๋จ๊ณ๋ก ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์๋ค.
Diffable DataSource ๋ฑ๋ก
Snapshot ๋ง๋ค๊ธฐ
Snapshot ์ ์ฉ
์ด์ ์์ธํ๊ฒ ์์๋ณด์.
Diffable DataSource ๋ฑ๋ก
UITableVIew๋ UICollectionView๋ฅผ ๋ง๋ค ๋, ๊ธฐ๋ณธ DataSource๋ฅผ ๋ฑ๋กํ๊ฒ ๋๋ค. ์ด๋ DiffableDataSource์ ๊ธฐ๋ณธ ๋ฐ์ดํฐ ๊ฐ์ ๋ฃ์ด์ค๋ค.
๋ณ๊ฒฝ ์ฌํญ์ด ์๊ธด ๊ฒฝ์ฐ Snapshot์ ๋ง๋ค๊ณ , Snapshot์ ์ ์ฉํ๋ค.
๊ธฐ์กด PrefetchData์ ๋น์ทํ ํํ์ด๋ค. ์ฆ, ๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ ๊ธฐ์ค์ผ๋ก snapshot์ ์์ฑํ๊ณ , data์ ๋ณ๊ฒฝ์ฌํญ์ ์ฒ๋ฆฌํ ํ์ snapshot์ ์ ์ฉ (apply)ํด์ฃผ๊ธฐ๋ง ํ๋ฉด UI๊ฐ ์์์ ๋ณ๊ฒฝ๋๋ ํํ์ด๋ค.
// ํ๋ฉด์ ๋ณด์ฌ์ค Item - Hashable protocol ์ฑํ ํ์
struct Shortcut: Hashable {
var title: String
var category: String
}
class ViewController: UIViewController {
enum Section {
case category
case popular
case latest
var headerTitle: String {
switch self {
case .category:
return "์นดํ
๊ณ ๋ฆฌ ๋ณ ๋จ์ถ์ด"
case .popular:
return "์ธ๊ธฐ์๋ ๋จ์ถ์ด"
case .latest:
return "์ต์ ๋จ์ถ์ด"
}
}
}
// diffable dataSource ์ ์ธ
private var dataSource: UITableViewDiffableDataSource<Section, Shortcut>!
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
setupDataSource()
setSnapshot()
}
// dataSource ๋ฑ๋ก
private func setupDataSource() {
dataSource = UITableViewDiffableDataSource<Section, Shortcut>(tableView: tableView) { tableView, indexPath, item in
guard let cell = tableView.dequeueReusableCell(withIdentifier: ShortcutTableViewCell.id, for: indexPath) as? ShortcutTableViewCell else { return UITableViewCell() }
cell.config(with: item)
return cell
}
}
private func setSnapshot() {
let category = [
Shortcut(title: "๋จ์ถ์ด1", subTitle: "๋จ์ถ์ด๋ฅผ ์จ๋ณด์ธ์"),
Shortcut(title: "๋จ์ถ์ด2", subTitle: "์ฝ๊ฒ ์จ ๋ณด์"),
Shortcut(title: "๋จ์ถ์ด3", subTitle: "๊ฟ๋ ์ข ๋นจ์๋ณด์")
]
let popular = [
Shortcut(title: "๋จ์ถ์ด4", subTitle: "๋จ์ถ์ด๋ฅผ ์จ๋ณด์ธ์"),
Shortcut(title: "๋จ์ถ์ด5", subTitle: "์ฝ๊ฒ ์จ ๋ณด์"),
Shortcut(title: "๋จ์ถ์ด6", subTitle: "๊ฟ๋ ์ข ๋นจ์๋ณด์")
]
let latest = [
Shortcut(title: "๋จ์ถ์ด7", subTitle: "๋จ์ถ์ด๋ฅผ ์จ๋ณด์ธ์"),
Shortcut(title: "๋จ์ถ์ด8", subTitle: "์ฝ๊ฒ ์จ ๋ณด์"),
Shortcut(title: "๋จ์ถ์ด9", subTitle: "๊ฟ๋ ์ข ๋นจ์๋ณด์")
]
// snapshot ์ ์ฉ
var snapshot = dataSource.snapshot()
snapshot.appendSections([.category, .latest, .popular])
snapshot.appendItems(category, toSection: .category)
snapshot.appendItems(popular, toSection: .popular)
snapshot.appendItems(latest, toSection: .latest)
dataSource.apply(snapshot)
}
}
Diffable DataSource๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ
snapshot ์์ฑ ๋ฐฉ๋ฒ์๋ 2๊ฐ์ง๊ฐ ์๋ค. - ๊ธฐ์กด dataSource๋ฅผ ๊ธฐ๋ฐ์ผ๋ก snapshot์ ์์ฑํ๋ ๋ฐฉ๋ฒ - ์๋ก์ด snapshot์ ์์ฑํ๋ ๋ฐฉ๋ฒ
์ฐ๋ฆฌ๋ ์ฌ๊ธฐ์ ์ ๋๊ฐ์ง ์์ฑ๋ฐฉ๋ฒ์ด ์์๊น? ๋ฅผ ๋ฐ๋์ ์๊ฐํด๋ด์ผํ๋ค. ์ฌ๊ธฐ์ ์ ค ์ค์ํ ๊ฐ๋ ์ ์ด๊ฑฐ๋ค.
๐ก diffableDataSource๋ snapshot์ ๋ง๋ค ๋, ๋ณต์ฌ๋ณธ์ return ํ๋ค.
๋ถ๋ช ์๊น ์ค๋ช ํ ๋, diffable data source๋ฅผ ๋ง๋ค๊ฒ ๋๋ฉด, viewController์๋ ์๋ณธ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ ํ์๊ฐ ์๋ค๊ณ ์ค๋ช ํ์๋ค. ๊ทธ๋ฐ๋ฐ, snapshot์ ๋ง๋ค ๋ ๋ณต์ฌ๋ณธ์ return ํ๋ค๊ณ ? ๋ง๋ ์๋๋ ์ํฉ์ธ๊ฑฐ๋ค. (์ด๊ฑฐ ๋๋ฌธ์ ์ง์ง ์ฝ์ง ์์ฒญ ๋ง์ด ํ๋ค)
์ดํด๊ฐ ์๋ ์๋ ์๊ธฐ ๋๋ฌธ์ ์กฐ๊ธ ๋ ์ค๋ช ์ ํด๋ณด์๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
๋ฌด์ ์ฌ์์ ์ด๋ค ์ท์ ๋ํด ์ข์์๋ฅผ ๋๋ ๋ค๊ณ ์๊ฐํด๋ณด์. ์ข์์๋ ID ๊ฐ์ด ์๋๋ค. ๋ฐ์ดํฐ๊ฐ ์์ด์ง๊ฑฐ๋ ์์ฑ๋๋ ์กฐ๊ฑด์ด ์๋๊ณ , ์์ฑ์ ์ผ๋ถ๋ถ์ด ์์ ๋ ๊ฒฝ์ฐ๊ฐ ๋๋ ๊ฒ์ด๋ค.
๋ค์ ์๊ฐํด๋ณด์. ์ฐ๋ฆฌ๋ dataSource์ snapshot์ ๊ฐ์ง๊ณ ์์ ๊ทธ snapshot์์ ๋ณ๊ฒฝ๋ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ์๋ค. ๊ทผ๋ฐ ์ด๊ฒ ์๋ณธ ๋ฐ์ดํฐ๊ฐ ์๋๋ผ โ๋ณต์ฌ๋ณธโ์ด๊ธฐ ๋๋ฌธ์, ์๋ฌด๋ฆฌ ๋ณต์ฌ๋ณธ์ ๋ณํ์ํจ๋ค๊ณ ํด๋, ๊ทธ ๋ณ๊ฒฝ์ด ๋ณด์ด์ง ์๋ ๊ฒ์ด๋ค.
์ฆ, ๊ธฐ์กด dataSource์ snapshot์ ๊ธฐ๋ฐ์ผ๋ก ์๋ฌด๋ฆฌ ์์ฑ์ ๋ณ๊ฒฝํด๋ด๋, ๋ฐ์ดํฐ๊ฐ ๋ณํ์ง ์๋๋ค๋๊ฒ์ด๋ค.
๊ทธ๋ผ ์ด๋ป๊ฒํ๋ฉด๋๋๋ฐ~!!!!!
๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๊ณ , ๋ค์ ๋ฃ์ด๋ผ~! ๋ผ๋๊ฒ Apple์ ๋ต๋ณ์ธ ๋ฏ ํ๋ค ^^
์ด๋ฅผ ์ํด insertItem(from: )
์ด๋ผ๋ ํจ์๊ฐ ์กด์ฌํ๋ค.
์ฆ, ์ฌ์ฉ์๊ฐ A๋ผ๋ ์ท์ ์ข์์๋ฅผ ๋๋ ๋ค๋ฉด, A๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๋ค๊ฐ insertItem์ ๊ธฐ๋ฐ์ผ๋ก ์์์น์ ์ฝ์ ์ํจ๋ค๋ฉด, ์ ํ์ด ์์์ ์ ๋๋ฉ์ด์ ์ ๋ณด์ฌ์ฃผ๊ฒ ๋ค~ ๋ผ๋ ๊ฒ์ด๋ค.
๊ทธ ์ด์ธ์๋ insert(before)์ด๋ผ๋ ํจ์๋ ์์ผ๋ ๋ฐ์ดํฐ ์์ ๊ณ ๋ คํด์ ๋๋ค๊ฐ ์์์ ์์ฑํด~ ๋์ insert(before: )๋ ๋ฐ์ดํฐ๊ฐ ์์ ๋ append๋ก ์๋ํ๊ฒ ๋ง๋ค์ด๋์ด~~~~ ๋ผ๋๊ฒ ์์ฝ~
indexPath
์ด์ ์ฐ๋ฆฌ๋ ViewController์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ง ์๋ค. diffableDataSource๊ฐ ๊ทธ ์ ๋ณด๋ฅผ ๋ชจ๋ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋๋ ์์ง ์ฐ๋ฆฌ๋ indexPath์ ๋ํ ์ ๋ณด๋ฅผ ์์์ผํ๋ค. ์๋! ์ด๋ค Cell์ ํญ ํ์ ๋, ๋ค๋ฅธ ๋ทฐ๋ก ์ด๋ํด์ผ๋๊ธฐ ๋๋ฌธ์ด๋ค. ์ฆ, UITableViewDelegate๋ฅผ ๊ตฌํํ ๋, indexPath์ ๋ณด๊ฐ ํ์ํ๋จ ๊ฒ์ด๋ค.
์ด์ ์ Item์ Hashable ํ๋กํ ์ฝ์ ์ง์ ํ๊ณ , ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๊ทธ Item์ ์ฐพ๋๋ฐ ์ ํ์๊ฐ์ ํ์ ์๊ฐ์ด ๊ฑธ๋ฆฐ๋ค. ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค. (optional๋ก return ํ๊ธฐ ๋๋ฌธ์ guard let ์ฌ์ฉ ์ถ์ฒ!)
let item = dataSource.itemIdentifier(for: indexPath)
๊ฐ๋ฐํ๋ฉฐ ๊ณ ๋ คํด์ผํ ์ (๊ทธ๋ฅ ์๋์ธ ๋ฏ)
apply()๋ BackgroundQueue์์ ๋์ํ๊ธฐ ๋๋ฌธ์, mainQueue๋ก ๊ฐ์ ธ์์ ์คํํ์
AirDrop๋ DiffableDataSource๋ก ๋ง๋ ๊ฑฐ์ผ~ ์ ๋๋ฉ์ด์ ๋ฉ์ง์ง?
์์
Advances in UI Data Sources - WWDC19 - Videos - Apple Developer
Last updated