ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

๋ฐ˜์‘ํ˜•

ios-og

๐ŸŽค Table View and Collection View

 

๐Ÿง Table View, Collection View ๋ž€?

  • UIScrollView์˜ ์„œ๋ธŒํด๋ž˜์Šค๋กœ ๋ฌดํ•œํ•œ ์–‘์˜(unbounded) ์ •๋ณด์— ๋ฌดํ•œํ•œ ์ ‘๊ทผ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ž๋ฃŒ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๋ฐฉ์‹์—์„œ ์ฐจ์ด๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
    • Table View: ์ •๋ณด๋ฅผ ํ•˜๋‚˜์˜ ๊ธด ๋ฆฌ์ŠคํŠธ๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค(์„น์…˜ ๋ถ„๋ฆฌ๋Š” ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค).
    • Collection View: ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ •๋ณด๋ฅผ 2D ํฌ๋งท์œผ๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค(์ฃผ๋กœ text flow ๊ฐ™์€ flowing์œผ๋กœ). ์—ฌ๊ธฐ์„œ text flow๋ž€ ๊ธ€์„ ์ฝ๋“ฏ์ด ์™ผ์ชฝ์—์„œ ์˜ค๋ฅธ์ชฝ์œผ๋กœ, ๊ทธ๋ฆฌ๊ณ  ๋‹ค์Œ ์ค„๋กœ ์ด์–ด์„œ ๊ณ„์† ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ปฌ๋ ‰์…˜ ๋ทฐ๋Š” ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒฐ๊ตญ ๋‘ View์˜ ์ฐจ์ด๋Š” ํ•˜๋‚˜๋Š” ํ–‰์œผ๋กœ ๋‚˜์—ดํ•˜์—ฌ ์ž๋ฃŒ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด๊ณ , ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” 2์ฐจ์›์œผ๋กœ ๋†“์—ฌ์ง„ ๋ฌด์ž‘์œ„์˜(arbitrary) ์•„์ดํ…œ์ด๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๐Ÿ“ Table View

  • Table View์˜ ๊ธฐ๋ณธ์ ์ธ ํ˜•ํƒœ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค
  • Table View์˜ ํ–‰์€ ๊ทธ๋ฃน์œผ๋กœ ๋ฌถ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋ฌถ์ธ ๊ทธ๋ฃน์€ ์„น์…˜์ด ๋ฉ๋‹ˆ๋‹ค. ์„น์…˜์€ ํ…Œ์ด๋ธ”์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๊ณ ์ •๋ (static) ๋•Œ๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์Œ์‹ ๋ฆฌ์ŠคํŠธ ๊ฐ™์ด ๋งค๋ฒˆ ๋ฐ”๋€Œ๋Š” ์ž„์˜์˜(arbitrary) ๋ฌด์ž‘์œ„ํ•œ ์ •๋ณด์—๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์„ค์ • ํ™”๋ฉด์˜ ๊ฒฝ์šฐ ํ•ญ์ƒ ๋‚ด์šฉ์ด ๊ณ ์ •๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Section์„ ํ™œ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๋Œ€ํ‘œ์ ์ธ Table View์˜ ์˜ˆ์‹œ๋กœ ์„ค์ •(settings) ํ™”๋ฉด์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

๐Ÿ“ฑ Collection View

  • Collection View์˜ ๊ธฐ๋ณธ์ ์ธ ํ˜•ํƒœ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ๊ธฐ๋ณธ์ ์œผ๋กœ 2D๋กœ ๋ฐฐ์น˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„์˜ ๊ทธ๋ฆผ์„ ๋ณด๋ฉด ํ–‰์ด ์กด์žฌํ•˜๋Š” ๊ฒƒ ๊ฐ™์ง€๋งŒ ์‹ค์ œ๋กœ ํ–‰์€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹จ์ˆœํžˆ ์ค„์—์„œ ์ค„๋กœ ๋ฐฐ์น˜๋œ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํฌ๊ธฐ๊ฐ€ ๋‹ฌ๋ž๋‹ค๋ฉด ํ–‰์ด ์กด์žฌํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • Collection View๋„ section์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๐Ÿง How to use?

  • ํŒ”๋ ˆํŠธ์—์„œ ์ง์ ‘ View๋ฅผ ๋“œ๋ž˜๊ทธํ•ด์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ํŒ”๋ ˆํŠธ์—์„œ Table์„ ๊ฒ€์ƒ‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.Table View๋ฅผ ์ง์ ‘ ๋„ฃ๊ฑฐ๋‚˜ Table View Controller๋ฅผ ํ†ตํ•ด ์ƒˆ๋กœ์šด Controller๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 
  • MVC์—์„œ ์ „์ฒด ๋ทฐ๊ฐ€ Table View์ด๊ฑฐ๋‚˜ Collection View๋ผ๋ฉด ์œ„์˜ Controller ์˜ต์…˜์„ ํ†ตํ•ด ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Collection View ์—ญ์‹œ ๋งˆ์ฐฌ๊ฐ€์ง€ ์ž…๋‹ˆ๋‹ค.

 

๐Ÿ“‚ Data๋ฅผ ์–ด๋””์—์„œ ๋ฐ›์„ ์ˆ˜ ์žˆ์„๊นŒ?

  • ์•ž์„œ ์–ธ๊ธ‰ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ MVC์—์„œ View๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ํ…Œ์ด๋ธ” ๋ทฐ์—์„œ ์ •์˜ํ•œ var(๋ณ€์ˆ˜)์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ…Œ์ด๋ธ” ๋ทฐ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฉ์‹์€ delegation๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • data Source๋ผ๋Š” ๋ณ€์ˆ˜๊ฐ€ ์žˆ๊ณ  View๊ฐ€ ์ด ๋ณ€์ˆ˜๋ฅผ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. dataSource์˜ ํƒ€์ž…์€ ํ”„๋กœํ† ์ฝœ์ด๊ณ  ์ด ํ”„๋กœํ† ์ฝœ์—๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๋Š” ํ•œ ๋ญ‰์น˜์˜ ๋ฉ”์†Œ๋“œ((bunch of methods)๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ table view๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

๐ŸŽฏ dataSource, delegate ๊ตฌํ˜„ํ•˜๊ธฐ

// Table View
var dataSource: UITableViewDataSource
var delegate: UITableViewDelegate

// Collection View
var dataSource: UICollectionViewDataSource
var delegate: UICollectionViewDelegate
  • UI-ViewDataSource์™€ UI-ViewDelegate์€ ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ํ•œ ๋ญ‰์น˜์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
    • numberOfSections: section์„ ๋‚˜๋ˆ„๋Š” ๋ฉ”์†Œ๋“œ๋กœ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์œผ๋ฉด ์„น์…˜ ๊ตฌ๋ถ„์ด ์—†์ด ํ•˜๋‚˜์˜ ์„น์…˜์ด ๋ฉ๋‹ˆ๋‹ค.
    • tableView or collectionView(numberOfRowsInSection): ํ•œ ์„น์…˜์— ๋ช‡๊ฐœ์˜ ํ–‰์ด ์žˆ๋Š”์ง€ ์ •ํ•˜๋Š” ๋ฉ”์†Œ๋“œ์ž…๋‹ˆ๋‹ค. ๊ฐ ์„น์…˜์— ์ง์ ‘ ๋ฌผ์–ด๋ณด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. Collection View์˜ ๊ฒฝ์šฐ์—๋Š” ์ด ์„น์…˜์— ๋ช‡ ๊ฐœ์˜ ์•„์ดํ…œ์ด ์žˆ๋Š”์ง€ ๋ฌป์Šต๋‹ˆ๋‹ค.
    • tableView or collectionView(cellForItemAt): ๊ฐ ํ–‰/์•„์ดํ…œ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๋ฉ”์†Œ๋“œ์ž…๋‹ˆ๋‹ค.
      ๐Ÿ“ IndexPath:
      • ๋งค์šฐ ์ž‘์€ ๊ตฌ์กฐ์ฒด์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ์„น์…˜๊ณผ ํ–‰ ๋˜๋Š” ์„น์…˜๊ณผ ์•„์ดํ…œ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์„น์…˜๊ณผ ํ–‰์„ ํ•ฉ์ณ์„œ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ Table View๋‚˜ Collection View๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•  ์ˆ˜ ์žˆ๊ณ , ์ด ๋ฉ”์†Œ๋“œ๋Š” IndexPath๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
      • IndexPath๋Š” ๋ณ€์ˆ˜๋กœ row, item, section์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
      ๐ŸŽฏ return type UI(Table/Collection)ViewCell:
      • ๋ฉ”์†Œ๋“œ์˜ return type์€ (Table View์˜ ๊ฒฝ์šฐ) UITableViewCell ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ UI ๋ทฐ์˜ ์„œ๋ธŒํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
      • ์ด view๋Š” ํ–‰์„ ๊ทธ๋ฆฌ๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
    • tableView ์•ˆ์— cell์„ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.cell์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ reuse ๋ฉ”์†Œ๋“œ๋ฅผ ๋ถ„์„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
    • func tableView(_ tv: UITV, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tv.dequeueReusableCell(withIdentifier: "MyCellId". for: indexPath) }
  • // UITableView func numberOfSections(in tableView: UITV) -> Int func tableView(_ tv: UITV, numberOfRowsInSection section: Int) -> Int func tableView(_ tv: UITV, cellForRowAt indexPath: IndexPath) -> UITableViewCell // UICollectionView func numberOfSections(in collectionView: UICV) -> Int func collectionView(_ tv: UICV, numberOfItemsInSection section: Int) -> Int func collectionView(_ tv: UICV, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

๐Ÿ“ Cell Reuse(์…€ ์žฌ์‚ฌ์šฉ)

  • ์•„์ดํŒŸ์— 10,000 ๊ณก์˜ ์Œ์•…์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ Table View๋กœ ๋ณด์—ฌ์ค„ ๋•Œ ์•จ๋ฒ” ์ž์ผ“, ๊ณก๋ช…, ๊ฐ€์ˆ˜ ๋“ฑ์˜ ์ •๋ณด๋Š” 10,000๊ฐœ์ด๊ณ  ๋งŒ ๊ฐœ์˜ UI ๋ทฐ๋ฅผ ๊ฐ–๋Š”๋‹ค๋Š” ๊ฒƒ์€ ๋งค์šฐ ๋น„ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์‹ค์ œ ํ…Œ์ด๋ธ” ๋ทฐ๋Š” ๋ณด์—ฌ์ง€๋Š” ํ–‰๋งŒ UI ํ…Œ์ด๋ธ” ๋ทฐ ์…€์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์Šคํฌ๋กค์„ ํ•ด์„œ ์–ด๋–ค ์…€์ด ๋งจ ์œ„๋กœ ๊ฐ€๊ฒŒ ๋ผ๋ฉด ์ด๋Š” ์žฌ์‚ฌ์šฉ๋˜์„œ ๋งจ ์•„๋ž˜์— ๋†“์—ฌ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์Šคํฌ๋กค์„ ํ•˜๋Š” ๋™์•ˆ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋ทฐ๋Š” ์žฌ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • ์œ„์˜ ๋‚ด์šฉ์„ ๊ตฌ์กฐ์ ์œผ๋กœ ์„ค๋ช…ํ•ด๋ณด๋ฉด ์Šคํฌ๋กค์„ ํ•  ๋•Œ ํ•˜๋‚˜์˜ UITableViewCell์€ ์žฌ์‚ฌ์šฉ ํ’€(a pool to be reused)๋กœ ๊ฐ€์„œ dequeueReusableCell ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์…€์„ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
    ๐Ÿง ์™œ ReusableCell์ด Queue๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์„๊นŒ ๊ณ ๋ฏผํ•ด๋ดค์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ์žˆ๋Š”๋ฐ ๋ง์ด์ฃ ! ์ฒ˜์Œ์—๋Š” data๊ฐ€ ๋‹ด๊ฒจ์žˆ๋Š” ์ฑ„๋กœ cell์— ์ €์žฅ๋˜์–ด ๋‚ด์šฉ์ด ๊บผ๋‚ด์ง„๋‹ค๊ณ  ์ƒ๊ฐํ•˜์—ฌ Stack์ด ๋” ๋งž์ง€์•Š์„๊นŒ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์Šคํฌ๋กค์„ ์œ„๋กœ ์˜ฌ๋ ค ์…€์ด ์‚ฌ๋ผ์กŒ๋‹ค๊ฐ€ ๋‹ค์‹œ ๋‚ด๋ฆฌ๋ฉด ์—ญ์ˆœ์œผ๋กœ ๋‚˜์™€์•ผ ํ•œ๋‹ค๋Š” ์ƒ๊ฐ์„ ํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ์…€ ์ž์ฒด๋งŒ ๋ฐ˜๋ณต์‚ฌ์šฉํ•˜๋Š” ๊ตฌ์กฐ์˜€์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋จผ์ € ๋“ค์–ด๊ฐ€ ์žˆ๋˜ ์…€์ด ๋จผ์ € ๋‚˜์˜ค๋Š” ๊ตฌ์กฐ๊ฐ€ ๋” ํ•ฉ๋ฆฌ์ ์ด๋ฏ€๋กœ FIFO(First In First Out)์˜ ๊ตฌ์กฐ๋กœ ๊ตฌํ˜„๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  • ๋งŒ์•ฝ์— ๋ฐฉ๊ธˆ ์Šคํฌ๋ฆฐ์ด ์ผœ์ ธ์„œ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Cell์ด ์—†์„ ๊ฒฝ์šฐ๋Š” ์–ด๋–ป๊ฒŒ ํ• ๊นŒ์š”? ๋ฐ”๋กœ ์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ๋งŒ๋“  ํ”„๋กœํ† ํƒ€์ž…์„ ๋ณต์‚ฌํ•ด์„œ ์ƒ์„ฑํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋ ˆ์ด๋ธ”, ๋ฒ„ํŠผ, ์ด๋ฏธ์ง€ ๋“ฑ์„ ์‚ฌ์šฉํ•ด์„œ ์…€์˜ ๋ชจ์–‘์„ ๋งŒ๋“ค๊ณ  ์˜คํ†  ๋ ˆ์ด์•„์›ƒ ๋“ฑ์„ ์‚ฌ์šฉํ•ด ์…€์„ ๊ณ ์ •์‹œํ‚ค๋ฉด ์…€์ด ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค๊ณ  ์ด๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.๊ทธ๋ž˜์„œ ์žฌ์‚ฌ์šฉํ•  ์…€์— ๋Œ€ํ•ด ๋งํ•˜๊ณ , ๋งŒ์•ฝ ์žฌ์‚ฌ์šฉํ•  ์…€์ด ์—†๋‹ค๋ฉด ์Šคํ† ๋ฆฌ๋ณด๋“œ์— ๋ณด์ด๋Š” ์ด ์…€์„ ๋ณต์‚ฌํ•ด์„œ ๋งŒ๋“ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์œ„์˜ ๊ตฌ๋ฌธ์„ ๋‹ค์‹œ ๋ถ„์„ํ•ด๋ณด๋ฉด"์ƒ์ˆ˜ cell์„ ์„ ์–ธํ•œ๋‹ค, UI Table View์˜ dequeueReusableCell์—์„œ "MyCellId"๋ผ๋Š” identifier๋ฅผ ๊ฐ€์ง„ Cell์„ indexPath์˜ ์ •๋ณด๋ฅผ ๋„ฃ์–ด ๊ฐ€์ ธ์˜จ๋‹ค"
  • ๋ผ๊ณ  ํ•ด์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • let cell = tv.dequeueReusableCell(withIdentifier: "MyCellId". for: indexPath)
  • Reuse์—์„œ ์ฃผ์˜ํ•ด์•ผํ•  ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.ํ•ด์„ํ•˜๋ฉด ์…€์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์— ์‹ฌ๊ฐํ•œ ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ด์•ผ๊ธฐ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์–ด๋–ค row์— ๋ถˆ๋Ÿฌ์™€์•ผํ•  ๋ฐ์ดํ„ฐ ์ค‘ ์ด๋ฏธ์ง€๊ฐ€ ์žˆ๊ณ  ํ•œ ์Šค๋ ˆ๋“œ์—์„œ ์ด๊ฒƒ์„ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์œ„ํ•ด ์ธํ„ฐ๋„ท์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ž‘์—…์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ž‘์—…์€ ์˜ค๋žœ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ ์‚ฌ์ด ์‚ฌ์šฉ์ž๊ฐ€ ์†๊ฐ€๋ฝ์œผ๋กœ ์Šคํฌ๋กคํ•ด์„œ ๊ทธ ์…€์„ ๋ณด๋‚ด๋ฒ„๋ฆฌ๊ณ  ์ด ์…€์€ ์žฌ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์•ฑ์€ ์ด๋ฏธ ๋‹ค๋ฅธ ์…€์˜ ๋‚ด์šฉ์„ ๋‹ด์•„ ๋ณด์—ฌ์ฃผ๋Š”๋ฐ ์ƒˆ๋กœ์šด ์ด๋ฏธ์ง€๊ฐ€ ์•„๋‹Œ ๊ธฐ์กด์— ์š”์ฒญ๋œ ์ด๋ฏธ์ง€๊ฐ€ ์…€์— ๋„์ฐฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์ฃผ์˜ํ•˜์ง€ ์•Š์œผ๋ฉด ๋‹ค๋ฅธ ์…€์˜ ์ด๋ฏธ์ง€๋ฅผ ์ƒˆ๋กœ์šด ์…€์— ๋ณด์—ฌ์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋ฏธ์ง€๊ฐ€ ์˜ค๋ฉด ์ด ์ด๋ฏธ์ง€๊ฐ€ ์ด๊ฒƒ์„ ์š”์ฒญํ•œ ์…€์ด ์—ฌ์ „ํžˆ ํ™”๋ฉด์— ๋ณด์—ฌ์ง€๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ผ๋ฐ˜์ ์ธ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ๋ฌธ์ œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋ฉด ํ™”๋ฉด์— ์—ฌ์ „ํžˆ ๋ฐ์ดํ„ฐ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์•„๋ž˜์™€ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.decision์€ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€, ์–ด๋–ค section์— ์กด์žฌํ•˜๋Š”์ง€ ๋“ฑ์— ๋”ฐ๋ผ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฐ์ •๋œ ๊ฒฐ๊ณผ๋Š” prototype์ด ๋˜๊ณ  ํ”„๋กœํ†  ํƒ€์ž… ์ž์ฒด๋ฅผ identifier๋กœ ๊ฒฐ์ •ํ•˜์—ฌ cell์„ ๋ถˆ๋Ÿฌ์˜ค๋ฉด ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์—์„œ ๋ฐœ์ƒํ•˜๋Š” cell reuse์— ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถˆ๋Ÿฌ์™€์ง€๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • func tableView(_ tv: UITV, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let prototype = decision ? "FoodCell" : "CustomFoodCell" let cell = tv.dequeueReusableCell(withIdentifier: prototype. for: indexPath) cell.textLabel?.text = food(at: indexPath) cell.detailTextLable?.text = emoji(at: indexPath) }
  • The fact that cells are reused has serious implications for multithreading!

 

๐Ÿ“‚ Loading up Cells(์…€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ)

 

  • ํ•œ article์„ ์ธ์šฉํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.์œ„์˜ ๋ฌธ์žฅ์„ ํ•ด์„ํ•ด๋ณด๋ฉด custom UI๋ฅผ UITableViewCell prototype์— ๋„ฃ์„ ๋•Œ outlet์ด ํ•„์š”ํ•˜์ง€๋งŒ Controller์— ์ง์ ‘ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๊ธฐ์กด์— IBOutlet์„ ํ†ตํ•ด ์—ฐ๊ฒฐํ–ˆ์„ ๋•Œ๋Š” ํ•˜๋‚˜์˜ ๊ฐ’์„ View์—์„œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ์œ„ํ•ด ์ง์ ‘ ์—ฐ๊ฒฐํ–ˆ๋Š”๋ฐ, TableView์—์„œ๋Š” ์—„์ฒญ๋‚˜๊ฒŒ ๋งŽ์€ cell์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ผ์ผ์ด ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋˜ ํ•˜๋‚˜์˜ single outlet์— ์—ฐ๊ฒฐ๋˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฐฐ์—ด ๋“ฑ์„ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š”๋ฐ ๊ทธ๋Ÿผ ๋„ˆ๋ฌด ๋ณต์žกํ•œ ๊ตฌ์กฐ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ฒ˜์Œ์œผ๋กœ outlet์„ View์— ๊ตฌํ˜„ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด View๋Š” UITableViewCell์˜ ์„œ๋ธŒํด๋ž˜์Šค์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ๊ฐ๊ฐ์˜ ํ–‰์€ ์ž์‹ ๋งŒ์˜ TableViewCell์ด ์žˆ๊ณ  ๊ฐ๊ฐ์˜ TableViewCell์€ ์ž์‹ ๋งŒ์˜ ์•„์šธ๋ ›์„ ๊ฐ€์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
    func tableView(_ tv: UITV, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let prototype = decision ? "FoodCell" : "CustomFoodCell"
        let cell = tv.dequeueReusableCell(withIdentifier: prototype. for: indexPath)
        if let myTVCell = cell as? MyTVC {
          myTVC.name = food(at: indexPath); myTVC.emoji = emoji(at: indexPath)
        }
    }
  • ์ปค์Šคํ…€ UITableViewCell ์„œ๋ธŒํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ์—๋Š” ๋ฐ˜๋“œ์‹œ ์ž‘์€ ํ”„๋กœํ† ํƒ€์ž… ํ–‰์ด ์„ ํƒ๋œ ์ƒํƒœ์—์„œ ์ง„ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด default๋กœ UITableViewCell ํด๋ž˜์Šค๋กœ ์„ค์ •๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— myTVC ํด๋ž˜์Šค๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
  • class myTVC: UITableViewCell { @IBOutlet var name: UILabel @IBOutlet var category: UILabel @IBOutlet var details: UILabel }
  • When we put custom UI into a UITableViewCell prototype, we probably need outlet to it.No, we can't, because there might be multiple rows with that type of cell
  • They can't all be hooked up to the same single outlet!
  • Can we hook them up directly to our Controller?

 

๐Ÿข Static Table View

  • staticํ•œ ํ…Œ์ด๋ธ” ๋ทฐ๋Š” ์ผ๋ฐ˜์ ์ธ ํ…Œ์ด๋ธ” ๋ทฐ์™€ ๋‹ค๋ฅด๊ฒŒ ๋ฌด์ž‘์œ„์˜(arbitrary) ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๊ณ ์ •๋œ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค(e.g. ์„ค์ • ํ™”๋ฉด). ์ด๋Ÿฐ ๊ฒฝ์šฐ๋Š” ํ–‰๊ณผ ์„น์…˜์˜ ๊ฐœ์ˆ˜๊ฐ€ ์ •ํ•ด์ ธ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ์ˆ˜๋ฅผ ์„ธ๋Š” ๋“ฑ์˜ ํ•จ์ˆ˜๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. cellForRowAt ์—ญ์‹œ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ์—๋Š” ์Šคํ† ๋ฆฌ๋ณด๋“œ์˜ ์ปจํŠธ๋กค๋Ÿฌ์— ํ–‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿง How to use?

โ€‹

  • ์œ„ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด Table View์˜ Content๋ฅผ Static Cells๋กœ ๋ฐ”๊ฟ”์ฃผ๊ณ  Style์„ Grouped๋กœ ์„ค์ •ํ•ด์ค๋‹ˆ๋‹ค.

 

๐Ÿ™‹ ๋งŒ์•ฝ ๋ชจ๋ธ์ด ๋ณ€๊ฒฝ๋œ๋‹ค๋ฉด?(What if your Model changes?)

 

  • ์•„์ดํŒŸ์— ์Œ์•…์ด ์ถ”๊ฐ€๋˜๊ฑฐ๋‚˜, ์Œ์‹ ๋ฆฌ์ŠคํŠธ์˜ ์Œ์‹์ด ์ถ”๊ฐ€๋  ๋•Œ Table View๋‚˜ Collection View๋Š” ์—…๋ฐ์ดํŠธ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ๋‘ View์—๋Š” reloadData() ๋ผ๋Š” function์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ๋ณด์—ฌ์ง€๋Š” ๋ชจ๋“  ์…€์— ๋Œ€ํ•ด ๋‹ค์‹œ ํ˜ธ์ถœ(reload)ํ•ฉ๋‹ˆ๋‹ค. ์•ฝ๊ฐ„ ๋ฌด๊ฑฐ์šด ๋ฉ”์†Œ๋“œ์ด์ง€๋งŒ ๊ทธ๋ ‡๊ฒŒ ๋ฌธ์ œ ๋  ๊ฒƒ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ์ „์ฒด๋ฅผ reload ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋ณด์—ฌ์ง€๋Š” ์…€์— ๋Œ€ํ•ด์„œ๋งŒ ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

๐Ÿ“ row์˜ ๋†’์ด ์„ค์ •ํ•˜๊ธฐ

 

  • Table์ด ๊ฐ€์ง„ Row์˜ ๋†’์ด๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์„ธ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
    1. rowHeight ์‚ฌ์šฉํ•˜๊ธฐ
    2. rowHeight๋Š” ํ…Œ์ด๋ธ” ๋ทฐ์˜ ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค. ์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ์„ค์ • ๊ฐ€๋Šฅํ•˜๋ฉฐ ํ•ญ์ƒ ๊ทธ ๋†’์ด๊ฐ€ ๋˜๋„๋ก ํ–‰์„ ๊ณ ์ •์‹œํ‚ต๋‹ˆ๋‹ค.
    3. ์˜คํ† ๋ ˆ์ด์•„์›ƒ ํ™œ์šฉํ•˜๊ธฐ
    4. Auto Layout์„ ํ™œ์šฉํ•ด ํ–‰ ๋†’์ด๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋ณต์žกํ•œ ๊ฒฝ์šฐ์˜ ์…€์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ณผ์ผ์— ๋Œ€ํ•œ ๋””ํ…Œ์ผํ•œ ์ •๋ณด๊ฐ€ ๋งŽ๋‹ค๋ฉด ์…€์˜ ํฌ๊ธฐ๋Š” ์ปค์ ธ์•ผํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋Œ€๋กœ ์ •๋ณด์˜ ์–‘์ด ์ž‘๋‹ค๋ฉด ์…€์˜ ํฌ๊ธฐ๋Š” ์ž‘์•„์ ธ์•ผํ•ฉ๋‹ˆ๋‹ค. ์ œ๋Œ€๋กœ ์„ค์ •ํ•œ๋‹ค๋ฉด ์ผ๋ฐ˜์ ์ธ ๋ทฐ๊ฐ€ ํ–‰์˜ ๋†’์ด๋ฅผ ์กฐ์ ˆํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ UIView๋ฅผ ํ–‰ ๋‚ด๋ถ€์—์„œ ์ƒ์œ„ ๋ทฐ๋กœ ๋†“๊ณ  ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๋“œ๋Ÿฌ๋‚ด๋Š” ์ œ์•ฝ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ–‰์˜ ๊ฐ€์žฅ์ž๋ฆฌ์— ๊ทธ ์ผ๋ฐ˜์ ์ธ ๋ทฐ๋ฅผ ๋“œ๋Ÿฌ๋‚ด๋„๋ก ์ œ์•ฝ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ…Œ์ด๋ธ” ๋ทฐ๊ฐ€ ๋‚˜ํƒ€๋‚˜๋ฉด ์˜คํ† ๋ ˆ์ด ์•„์›ƒ์œผ๋กœ์ธํ•ด ์–ด๋–ค ํฌ๊ธฐ๋ฅผ ๊ฐ€์ ธ์•ผํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด 1๋ฒˆ์˜ rowHeight๊ฐ€ ์•„๋‹ˆ๋ผ UITableViewAutomaticDimension์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    5. tableView ๋ฉ”์†Œ๋“œ ์ด์šฉํ•˜๊ธฐ
    6. tableView(heightForRowAt indexPath: ) ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด row์˜ ๋†’์ด๋ฅผ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฉ”์†Œ๋“œ๋Š” ํ•ด๋‹น ์ธ๋ฑ์Šค๋ฅผ ๊ฐ€์ง„ ํ–‰์˜ ๋†’์ด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. Auto Layout ์—†์ด ํšจ๊ณผ์ ์œผ๋กœ ๋†’์ด๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ด๊ฒƒ์€ ์ข‹์€ ๋ฐฉ์‹์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Collection View์˜ ๊ฒฝ์šฐ๋„ ๊ธฐ๋ณธ์ ์œผ๋กœ Table View์™€ ๊ฐ™์ง€๋งŒ sizeForItemAt์ด๋ผ๋Š” ์š”์†Œ๊ฐ€ ํ•˜๋‚˜ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด Collection View๋Š” ์ค„๋กœ ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํ•˜๋‚˜์˜ ์š”์†Œ๊ฐ€ Rectangleํ•˜๊ฒŒ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๊ณตํ†ต์ ์ธ ๋†’์ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

 

๐Ÿฆ„ Table View์˜ Header ๋„ฃ๊ธฐ

  • Table View๊ฐ€ ์—ฌ๋Ÿฌ ์„น์…˜์„ ๊ฐ€์ง€๊ณ  ์žˆ์„ ๋•Œ ์„น์…˜์˜ ์ด๋ฆ„(header)์„ ๋„ฃ๋Š” ๊ฒƒ์€ ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • func tableView(_ tv: UITV, titleForHeaderInSection section: Int) -> String?

Reference: Stanford CS193p by Paul Hegarty

๋ฐ˜์‘ํ˜•
๋Œ“๊ธ€
๋ฐ˜์‘ํ˜•
๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
TAG more
ยซ   2024/11   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
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
๊ธ€ ๋ณด๊ด€ํ•จ