🌱 SeSAC

[SeSAC] 220719 TIL

taeeekki 2022. 7. 21. 23:05

TableView Row(ν–‰) 높이

일괄적인 ν–‰ 높이λ₯Ό μ‘°μ ˆν•˜λŠ” 것이라면, μ „μžμ˜ μ½”λ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 더 λ‚˜μ•„λ³΄μΈλ‹€.

self.tableView.rowHeight = 80
// μ…€μ˜ 높이(μ˜΅μ…˜, λΉˆλ„ 높은) (feat. tableView.rowHeight)
// λ©”μ„œλ“œμ˜ μš°μ„  μˆœμœ„κ°€ 더 λ†’λ‹€.
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 100
}

 


 

μ‚Όν•­μ—°μ‚°μžμ˜ μ‚¬μš©

μ‚Όν•­μ—°μ‚°μžλ₯Ό 처음 μ•Œκ²Œ λ˜μ—ˆμ„ λ•Œ, 정말 λͺ¨λ“  뢀뢄에 μ½”λ“œλ₯Ό λ‚¨μš©ν–ˆμ—ˆλ‹€. 그런데 μ‚¬μš©ν•˜λ‹€λ³΄λ‹ˆ 였히렀 μ½”λ“œλ₯Ό μ΄ν•΄ν•˜λŠ” 데 μ‹œκ°„μ΄ κ±Έλ¦¬λŠ” κ²½μš°λ„ λ§Žμ•˜κ³ , μ—¬λŸ¬ 쑰건이 겹쳐 μžˆλŠ” κ²½μš°μ—λŠ” μ‚¬μš©ν•˜κΈ° μ–΄λ €μ› λ‹€. 그렇기에 μ μ ˆν•œ μˆœκ°„μ— μ‚¬μš©ν•˜λŠ” 것이 ν•„μš”ν•˜λ‹€κ³  생각이 λ“€μ—ˆλ‹€. μ‚Όν•­μ—°μ‚°μžμ˜ μ‚¬μš©μ„ 였히렀 μ§€μ–‘ν•˜λŠ” 것이 μ’‹μ•„λ³΄μ˜€κ³ , 정말 κ°„λ‹¨ν•œ λΆ€λΆ„μ—λ§Œ μ‚¬μš©ν•˜λŠ” 것이 쒋아보인닀.

if indexPath.row % 2 == 0 {
  cell.imageView?.image = UIImage(systemName: "star")
  cell.backgroundColor = .white
} else {
  cell.imageView?.image = UIImage(systemName: "star.fill")
  cell.backgroundColor = .systemGray6
}
cell.imageView?.image = indexPath.row % 2 == 0 ? UIImage(systemName: "star") : UIImage(systemName: "star.fill")
cell.backgroundColor = indexPath.row % 2 == 0 ? .white : .systemGray6

 


 

셀을 2개 이상 μ‚¬μš©ν•œλ‹€λ©΄?

ν•˜λ‚˜μ˜ ν…Œμ΄λΈ” λ·°μ—μ„œ μ—¬λŸ¬ 개의 셀을 μ‚¬μš©ν•˜κ³  싢은 κ²½μš°κ°€ μžˆλ‹€. 이런 경우 μ‹œμŠ€ν…œμ΄ μ μ ˆν•œ 셀을 꺼내와 ν…Œμ΄λΈ”λ·°μ— λΏŒλ €μ€„ 수 μžˆμ–΄μ•Ό ν•˜λŠ”λ° 그것을 κ°€λŠ₯ν•˜κ²Œ ν•˜λ„λ‘ identifierκ°€ μ‚¬μš©λœλ‹€. μ…€μ˜ μ΄λ¦„ν‘œλΌκ³  μƒκ°ν•˜λ©΄ νŽΈν•  것 κ°™λ‹€.

 


 

μž¬μ‚¬μš© λ©”μ»€λ‹ˆμ¦˜

1000개의 셀을 화면에 보여쀄 것이라고 ν•΄μ„œ 셀을 ν•œ λ²ˆμ— λ‹€ λ§Œλ“€μ–΄λ†“λŠ” 것은 μ•„λ‹ˆλ‹€. ν™”λ©΄μ—λŠ” λ‹Ήμž₯ ν•„μš”ν•œ μ…€λ§Œ 보여주고 λ§Œλ“€μ–΄ 놓은 셀을 μž¬μ‚¬μš©ν•˜λŠ” ꡬ쑰둜 이루어진닀. λ”₯ν•œ λ©”μ»€λ‹ˆμ¦˜μ€ 이후에 μ•Œμ•„λ³΄λ„λ‘ ν•˜μž.

 

 


 

Enum을 ν™œμš©ν•œ μ½”λ“œ κ°œμ„ 

우츑 화면을 μ–΄λ–»κ²Œ ꡬ성할 수 μžˆμ„κΉŒ? κ°„λ‹¨ν•˜κ²Œ TableViewControllerλ₯Ό μ΄μš©ν•΄λ³΄λ„λ‘ ν•˜μž.

 

CaseIterable

μ—΄κ±°ν˜•μ„ λ°°μ—΄μ²˜λŸΌ μ‚¬μš©ν•  수 μžˆλ„λ‘ λ„μ™€μ£ΌλŠ” ν”„λ‘œν† μ½œ

CustomStringConvertible

μ•„λž˜ 링크 μ°Έκ³ 
[Swift] CustomStringConvertible

ν•œκ°€μ§€ μƒˆλ‘œ μ•Œκ²Œλœ 것은 CustomStringConvertible ν”„λ‘œν† μ½œμ„ μ±„νƒν•˜κ³ , 좜λ ₯을 ν•˜λ©΄ description으둜 μ •ν•΄ 놓은 String κ°’μœΌλ‘œ 좜λ ₯되길래 κ·Έ λ™μ•ˆ Type μ—­μ‹œ String인 쀄 μ•Œμ•˜μ§€λ§Œ Type은 κ·ΈλŒ€λ‘œ μ—΄κ±°ν˜• νƒ€μž…μ΄μ—ˆλ‹€. print(SettingType.total)와 같이 좜λ ₯을 ν•˜λ©΄ "전체 μ„€μ •"κ³Ό 같이 좜λ ₯λ˜λŠ”λ° 이λ₯Ό ν—€λ”μ˜ 타이λ₯Όλ‘œ μ‚¬μš©ν•  수 μ—†μ—ˆλ˜ μ΄μœ λŠ” String νƒ€μž…μ΄ μ•„λ‹ˆλΌ μ—΄κ±°ν˜• νƒ€μž…μ΄μ—ˆκΈ° λ•Œλ¬Έμ΄λ‹€. κ·Έλž˜μ„œ String으둜 λ³€ν™˜ν•΄μ£Όμ–΄μ„œ μ½”λ“œλ₯Ό μž‘μ„±ν•˜μ˜€λ‹€.

// λ‹€μŒκ³Ό 같은 μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œλ„ μžˆλ”λΌ.
String(describing: <#T##CustomStringConvertible#>)

 

λ‚˜μ˜ 경우 μ•„λž˜μ™€ 같이 μ½”λ“œλ₯Ό μž‘μ„±ν•΄μ„œ μœ„μ˜ 화면을 κ΅¬ν˜„ν–ˆλ‹€.

import UIKit

enum SettingType: CaseIterable, CustomStringConvertible {
    case total
    case personal
    case etc

    var contents: [String] {
        switch self {
        case .total:
            return ["곡지사항", "μ‹€ν—˜μ‹€", "버전 정보"]
        case .personal:
            return ["개인/λ³΄μ•ˆ", "μ•Œλ¦Ό", "μ±„νŒ…", "λ©€ν‹°ν”„λ‘œν•„"]
        case .etc:
            return ["고객센터/도움말"]
        }
    }
    
    var numberOfRowInSections: Int {
        return contents.count
    }
    
    var description: String {
        switch self {
        case .total:
            return "전체 μ„€μ •"
        case .personal:
            return "개인 μ„€μ •"
        case .etc:
            return "기타"
        }
    }
}

final class SettingViewController: UITableViewController {
    override func numberOfSections(in tableView: UITableView) -> Int {
        return SettingType.allCases.count
    }
    
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return String(describing: SettingType.allCases[section])
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return SettingType.allCases[section].numberOfRowInSections
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "settingCell") else { return UITableViewCell() }
        cell.textLabel?.text = SettingType.allCases[indexPath.section].contents[indexPath.row]
        return cell
    }
}

 


 

λ„€λΉ„κ²Œμ΄μ…˜ 컨트둀러 μ§€μ • μœ„μΉ˜

  1. νƒ­ λ°” + λ„€λΉ„κ²Œμ΄μ…˜
  2. λ„€λΉ„κ²Œμ΄μ…˜ + 각 Child λ·° 컨트둀러
  • 1번의 경우, 각 λ·° 컨트둀러의 νƒ­ λ°” μ•„μ΄ν…œμ„ μ„€μ •ν•˜κΈ°κ°€ νŽΈν•˜λ‹€.
  • 2번의 경우, λ„€λΉ„κ²Œμ΄μ…˜ λ°” κ΅¬ν˜„μ΄ νŽΈν•˜λ‹€. λ„€λΉ„κ²Œμ΄μ…˜ λ°” 타이틀, μ•„μ΄ν…œμ„ μ„€μ •ν•˜κΈ°κ°€ νŽΈν•˜λ‹€.

 


 

Extension

  • ν•„μš”ν•œ μš”μ†Œλ“€λ§Œ μ΅μŠ€ν…μ…˜μœΌλ‘œ λ§Œλ“€μž.
  • ν•œ κ΅°λ°μ—μ„œλ§Œ μ‚¬μš©ν•œλ‹€λ©΄ μ΅μŠ€ν…μ…˜μœΌλ‘œ λ§Œλ“€μ§€ μ•ŠλŠ” 것이 μ’‹λ‹€.
  • UIViewController+Extension μ•ˆμ— 100개의 ν•¨μˆ˜λ₯Ό μΆ”κ°€λ‘œ μ„ μ–Έν•΄λ†“μ•˜λ‹€κ³  κ°€μ •ν•΄λ³΄μž. UIViewControllerλ₯Ό μƒμ†ν•΄μ˜€κ±°λ‚˜ μ‚¬μš©ν•˜λ €κ³  ν•  λ•Œ κ·Έ ν•¨μˆ˜λ“€κΉŒμ§€ 뢈러였기 λ•Œλ¬Έμ— λΆˆν•„μš”ν•œ 호좜이 일어날 수 있고 λ¬΄κ±°μ›Œμ§„λ‹€.

 


 

Store Property

  • μ €μž₯ ν”„λ‘œνΌν‹°λŠ” 포함할 수 μ—†λ‹€.
  • μ„ μ–Έν•˜λŠ” μ‹œμ μ— λ©”λͺ¨λ¦¬μ— μ˜¬λΌκ°€κΈ° λ•Œλ¬Έμ— ν™•μž₯의 ν˜•νƒœλ‘œ μ‚¬μš©ν•  수 μ—†λ‹€.
  • cf) λ©”μ„œλ“œλŠ” ν˜ΈμΆœν•˜λŠ” μ‹œμ μ— μ‚¬μš©λ˜κΈ° λ•Œλ¬Έμ— ν™•μž₯을 ν•  수 μžˆλŠ” 것이닀.

 


 

Issue

  • TableView ViewController μ—°κ²° 이슈 (Xcode 끄고 켜기, Clean Build Folder, μ—­μœΌλ‘œ μ—°κ²°ν•˜κΈ°)
  • Identifier 휴먼 μ—λŸ¬ (Cell IdλŠ” μ •ν™•νžˆ μ“°μž)
  • numberOfRowInSection (λ©”μ„œλ“œ μ •ν™•νžˆ μ‚¬μš©ν•˜μž)

 


 

μ»€μŠ€ν…€ μ…€ μƒμ„±ν•˜κΈ°

  • μ…€ 클래슀 파일 생성
  • μ…€κ³Ό 클래슀 μ—°κ²° (μ •ν™•νžˆ λ§€μΉ­μ‹œμΌœμ£Όμ–΄μ•Ό 함)
  • μ…€ identifier μ„€μ •
  • μ…€ κΊΌλ‚΄κΈ°

 


 

μ…€ μΆ”κ°€ν•˜κΈ°(κ°±μ‹ ν•˜κΈ°)

ReloadData

배열에 데이터λ₯Ό 잘 μΆ”κ°€ν•΄μ€€λ‹€κ³  해도, ν…Œμ΄λΈ”λ·°μ—λŠ” λ³€κ²½ 사항이 λ°˜μ˜λ˜μ§€ μ•ŠλŠ”λ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— UIλ₯Ό λ‹€μ‹œ 그리라고 TableView에 μš”μ²­ν•  ν•„μš”κ°€ μžˆλ‹€. 데이터가 λ‹¬λΌμ§€λŠ” μ‹œμ μ— 적절히 μš”μ²­λ˜μ–΄μ•Ό ν•œλ‹€. λ‹€μŒκ³Ό 같은 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•΄μ„œ ν…Œμ΄λΈ”λ·°λ₯Ό λ‹€μ‹œ 그리도둝 ν•œλ‹€.

tableView.reloadData()

reloadData()μ‹œμ μ—λŠ” λ‹€μŒ μž‘μ—…μ΄ μ‹€ν–‰λœλ‹€.

  • numberOfItemsInSection λ©”μ„œλ“œ : cell의 개수 κ²°μ •
  • cellForItemAt λ©”μ„œλ“œ : 화면에 λ³΄μ—¬μ§ˆ 만큼의 μ…€ 생성

맀번 전체λ₯Ό κ°±μ‹ ν•΄μ•Ό ν• κΉŒ?

Section, Row만 κ°±μ‹ ν•  μˆ˜λ„ μžˆλ‹€. 적절히 μ„ νƒν•΄μ„œ μ‚¬μš©ν•˜λ„λ‘ ν•˜μž.

  • reloadSections()
  • reloadRows()

μ˜ˆμ‹œ μ½”λ“œ

import UIKit

class BucketlistTableViewController: UITableViewController {

    var list = ["λ²”μ£„λ„μ‹œ", "탑건", "ν† λ₯΄"]
    
    @IBOutlet weak var userTextField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.rowHeight = 90
    }
    
    @IBAction func userTextFieldDidFinish(_ sender: UITextField) {
        self.list.append(sender.text!)
        self.tableView.reloadData()
    }
}

// MARK: - Methods

extension BucketlistTableViewController {
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.list.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: BucketlistTableViewCell.self), for: indexPath) as! BucketlistTableViewCell
        cell.bucketlistLabel.text = self.list[indexPath.row]
        cell.bucketlistLabel.font = .boldSystemFont(ofSize: 18)
        return cell
    }
}

 


 

ν…Œμ΄λΈ”λ·° κ΄€λ ¨ λ©”μ„œλ“œ 및 κΈ°λŠ₯

슀크둀 μ‹œ ν‚€λ³΄λ“œ dismiss

Reload

self.tableView.reloadData()
self.tableView.reloadSections(IndexSet(0...0), with: .fade)
self.tableView.reloadRows(at: [IndexPath(row: 0, section: 0), IndexPath(row: 1, section: 0)], with: .fade)

Move & Swipe

override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
    // μ…€ 이동
}

override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    // μ‚­μ œ
}

override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    // 즐겨찾기 ν•€ κ³ μ •
}

Default Edit(+Delete)

// νŽΈμ§‘ κ°€λŠ₯ν•œ μƒνƒœλ‘œ λ§Œλ“€ 수 있음
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
}

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        // λ°°μ—΄ μ‚­μ œ 후에 ν…Œμ΄λΈ” λ·° κ°±μ‹ 
        list.remove(at: indexPath.row)
        tableView.reloadSections(IndexSet(0...0), with: .automatic)
    }
}