- ํ ํ๋ก์ ํธ(2์ธ)
- ํ๋ก์ ํธ ๊ธฐ๊ฐ: 2021.12.06 ~ 2021.12.17
- ํค์๋
- ํ๋ก์ ํธ ์๊ฐ
- ํ๋ก์ ํธ ์ฃผ์๊ธฐ๋ฅ
- Trouble Shooting
- "๋ค๋น๊ฒ์ด์ ๋ฐ๋ฅผ ํน์ ViewController์์๋ง ์จ๊น ์ฒ๋ฆฌํ๋ ค๋ฉด?"
- "์ ์ด Select ๋์์ ๋ ์ฌ๋ผ์ง์ง ์๋ ํ์๋ฐฐ๊ฒฝ"
- "ํ๋ฉด ์ ํ ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ์ฌ๋ฌ๊ฐ์ง ๋ฐฉ๋ฒ"
- "attributedText๋ฅผ ์ ์ฉํด์ค Label์ Dynamic Type ์ ์ฉํ๊ธฐ"
- "๋ฉ์ธ์ ํ๋จ ๋ฒํผ์ด ์ Label๊ณผ ๊ฒน์ณ๋ณด์ด๋ ํ์"
- "ํน์ ํ๋ฉด๋ง Orientation ๊ณ ์ "
- ์๋กญ๊ฒ ์๊ฒ๋ ๊ฒ
- ๊ธฐ์ ์ ๋์
JSON
Codable
Decodable
Encodable
MVC
TableView
Cell Reuse
TableView Delegate, DataSource
TableView register
xib
NSMutableAttributedString
Result
Auto Layout
ImageVIew
Navigation Controller
Orientations
Accessibility
Dynamic Type
Voice over
static
UIButton
Configuration
UITableView, JSON์ ํ์ฉํ ์ฑ์ด์์.
๋ค์ํ ๊ตญ๊ฐ์ ๋ฌธํ์ ์ฐ ๋ฆฌ์คํธ๋ฅผ ๋ณผ ์ ์์ด์ ! ๐
-
์ํฉ
MainViewController๋ฅผ ์ ์ธํ ๋๋จธ์ง ๋ทฐ๋ ๋ค๋น๊ฒ์ด์ ๋ฐ๊ฐ ์กด์ฌํ๋ค. ์ฆ MainViewController๋ ๋ค๋น๊ฒ์ด์ ๋ฐ๋ฅผ ์จ๊น์ฒ๋ฆฌ ํด์ผ ํ๋ค. -
์๋
์คํ ๋ฆฌ๋ณด๋์์ ๊ฐ์ถ๊ธฐ -
์ฝ๋๋ก ๊ฐ์ถ๊ธฐ
- ๋ค๋น๊ฒ์ด์
์ปจํธ๋กค๋ฌ๋ก Embed In ๋์ด์๋ ViewController ๋ด๋ถ์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ค๋ค.
self.navigationController?.isNavigationBarHidden = true
- ๋ค๋น๊ฒ์ด์
์ปจํธ๋กค๋ฌ๋ก Embed In ๋์ด์๋ ViewController ๋ด๋ถ์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ค๋ค.
-
์ด์
์์ ๊ฐ์ ๋ฐฉ๋ฒ์ Navigation Controller์ ์ฐ๊ฒฐ๋์ด์๋ ๋ชจ๋ ViewController์ Navigation Bar๊ฐ ์จ๊ฒจ์ง๋ค. -
ํน์ ViewController์ Navigation Bar๋ฅผ ์จ๊ธฐ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ด ์๋ค.
-
ํด๊ฒฐ
ํด๋น ๋ฐฉ๋ฒ์ View Life Cycle ๋ฉ์๋๋ฅผ ํ์ฉํ์ฌ ๋ทฐ๊ฐ ํ๋ฉด์ ๋ณด์ผ ๋ Navigation Bar๋ฅผ ์จ๊ธฐ๊ณ ๋ค๋ฅธ์ฐฝ์ผ๋ก ๋์ด๊ฐ๋ ๋ค์ ๋ณด์ด๊ฒํ๋ ๋ฐฉ๋ฒ์ด๋ค.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: animated)
}
-
์ํฉ
์ ์ ํด๋ฆญํด์ ํ๋ฉด์ ํํ ๋ค์ ๋์์๋ ์ ์ ๋ฐฐ๊ฒฝ์์ด ์์์ด์ง๋ ํ์์ด ์ผ์ด๋ฌ๋ค. -
์ด์
ํ ์ด๋ธ๋ทฐ์ ์ ์ด ์ ํ๋๋ฉด ํ์์ผ๋ก ๋ณํ๊ฒ ๋๋๋ฐ, ๋ฌธ์ ๋ ์ด๋ ๊ฒ ๋ณํ ์์ด ๊ทธ๋๋ก ์ ์ง๋๋ค. -
ํด๊ฒฐ
ํ ์ด๋ธ ๋ทฐ์ ์ ์ ์ ํํ๋ฉด ํ์์ผ๋ก ๋ณํ๋ค๊ฐ ๋ค์ ์๋ ์์ผ๋ก ๋ฐ๋ก ๋์์ค๊ฒ ํ๋ ค๋ฉด ์๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ์ ์ ํฐ์น๊ฐ ์๋ฃ๋์์ ๋, deselect๋๋๋ก ํ๋ฉด ๋๋ค.extension ItemListViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) } }
-
์ ์ฉํ
- ๋ฆฌ์คํธ์์ ์์ธ๋ณด๊ธฐ๋ก ํ๋ฉด์ ํ์ด ๋ ๋ ํด๋น ์ ์ ํด๋นํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ํ๋ฉด์ผ๋ก ๋๊ฒจ์ฃผ๊ธฐ ์ํด ๋ค์ํ ๋ฐฉ๋ฒ๋ค์ ๊ณ ๋ฏผํด๋ณด์๋ค.
1
performSegue์ sender๋ฅผ nil์ด ์๋๋ผ ์ ๋ฌํ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅํ prepare์sender
๋ฅผ ๋ค์ด์บ์คํ ์ ํ์ฉํ์ฌ ์ ๋ฌํ ์ ์๋ค.
extension ItemListViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "ItemDetailView", sender: items[indexPath.row])
tableView.deselectRow(at: indexPath, animated: true)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let item = sender as? ExpositionItem,
let nextViewController = segue.destination as? ItemDetailViewController else {
return
}
nextViewController.item = item
}
2
prepare ๋ฉ์๋ ๋ด๋ถ์์ ์ ํ๋ ์ ์indexPath
๋ฅผ ๊ตฌํด์ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ๋ ์กด์ฌํ๋ค.
extension ItemListViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "ItemDetailView", sender: nil)
tableView.deselectRow(at: indexPath, animated: true)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let indexPath = itemListTableVIew.indexPathForSelectedRow,
let nextViewController = segue.destination as? ItemDetailViewController else {
return
}
nextViewController.item = items[indexPath.row]
}
์ํฉ
๋ถ๋ถ์ ์ผ๋ก ํ ์คํธ ํฌ๊ธฐ ํธ์งํด์ค ๊ธ์๋ค์ด ์ค์๊ฐ์ผ๋ก Dynamic Type์ด ์ ์ฉ์ด ์๋๋ ํ์์ด ๋ฐ์ํ๋ค.์ด์
์๊ณ ๋ณด๋ ํธ์งํด์ค ๋ถ๋ถ(prefix)์ ์ ์ธํ ๋๋จธ์ง ๊ธ์์ ํฐํธ๋ ํฌ๊ธฐ๋ฟ๋ง ์๋๋ผ ๋ค์ด๋๋ฏน ํ์ ๋ ๊ฐ์ด ์ ์ฉํด์ค์ผ ๋ฌ๋ค.- ๋งจ ์ฒ์ ๊ธ์์ TextStyle์ด title3๋ก ์ค์ ๋์ด์๋๋ฐ addAttribute๋ฅผ ํ๋ ์๊ฐ TextStyle์ด ํ๋ฆฌ๋ ๊ฒ ๊ฐ๋ค.
ํด๊ฒฐ
๋ฐ๋ผ์ ๋๋จธ์ง ํ ์คํธ์ ๋ํด์๋ TextStyle์ ์ง์ ํด์ค ํ addAttribute ํด์ฃผ๋ ํด๊ฒฐ๋์๋ค.
-
์ํฉ
Dynamic Type์ ์ต๋ํ ๋๋ ธ์ ๋ ํ๋จ์ ๋ฒํผ titleLabel์ด ์ปค์ก์ง๋ง ์ด์ ๋ฐ๋ผ StackView์ ๋์ด๊ฐ ๋์ด๋์ง ์๋ ํ์์ด ๋ํ๋ฌ๋ค. -
-
์๋1
๋ ์ด์์์ด ์์กํ ์์ด์ ๊ทธ๋ฐ๊ฑด๊ฐ ์ถ์ด์ ๋ฒํผ์ ๋์ด๋ฅผ ์คํ๋ทฐ์ ๊ฐ๊ฒ ์ค์ ์ ์ฃผ์์ผ๋ ํ์์ ๋์ผํ๋ค. -
์๋2
๋ํ StackView์ Alignment๋ฅผ center๋ก ์ฃผ์์ ๋์๋ ์ฝ๊ฐ ๊ฒน์ณ์ง์ด ์ค๊ธด ํ์ง๋ง ๋์ผํ ๋ฌธ์ ๋ก ํด๊ฒฐ์ ๋์ง ์์๋ค. -
ํด๊ฒฐ
๋ฒํผ์ Style์ด ์ด์ ์ ๋ฒ์ ํธํ ๋ฌธ์ ๋ก default๋ก ๋ง์ถฐ์ ธ ์์๋๋ฐ,iOS 15๋ถํฐ ์ ์ฉ ๊ฐ๋ฅํ Plain
์ผ๋ก ๋ณ๊ฒฝํด์ฃผ์ ๋ ์ด์์ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์๋ค. ๊ทธ๋ฌ๋ ์ด๋ค ์ฐจ์ด๋ก ํด๋น ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์๋์ง ์ ํํ ํ์ ์ ์ด๋ ค์ ๋ค. ๊ธฐ์กด์ Dynamic Type์ด ์ ์ฉ๋์ง ์์๋ ๋ฒํผ์ด ์ด๋ฒ์ ์ ๋ฐ์ดํธ๊ฐ ๋๋ฉด์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ฉ๋๊ฒ๋ ๋ฐ๋์๋๋ฐ ๊ทธ ๋ถ๋ถ ๋๋ฌธ์ด ์๋๊ฐ ์ถ๋ค.
์ํฉ
์ฒซ๋ฒ์งธ ๋ทฐ์ธ MainView๋ง Orientation์ ๊ณ ์ ํด์ฃผ๊ณ ์ถ์๋๋ฐ, ์ฝ๋๋ก ์ ์ฉ์ ํด์ฃผ๋ คํด๋ ๋ณํ๊ฐ ์๋ ํ์์ด ๋ํ๋ฌ๋ค.override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return .portrait }
์ด์
์ ํ๋กํผํฐ๋ฅผ overrideํ์ฌ ํ๋ฉด ๊ณ ์ ์ ํด์ฃผ๊ณ ์ถ์์ง๋ง ์ ์ฉ์ด ๋์ง์์๊ณ , ์ด์ ๋ฅผ ์ฐพ์๋ณด๋ ์ด๋ฒ ํ๋ก์ ํธ์ ๋ทฐ๋ค์ Hierarchy ์๋จ์ NavigationController๊ฐ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์๋จ ๋ทฐ์ Orientation์ด ๊ณ ์ ๋์ด์์ง ์์ ํ์ ๋ทฐ๋ค์ Orientation ๋ํ ์ ์ฉ๋์ง ์๋ ๊ฒ์ด์๋ค.ํด๊ฒฐ
Navigation์ ํด๋์ค๋ฅผ ์๋ก ์์ฑํ์ฌ Orientation์ ์ ์ฉ์์ผ์ค๊น ํ์ง๋ง, Main๋ทฐ๋ง ๊ณ ์ ์์ผ์ฃผ๊ณ ์ถ์๊ธฐ๋๋ฌธ์ ๊ตณ์ด ์์ฑ์น์๊ณ , UINavigationControllerDelegate๋ฅผ MainViewController์ ์ฑํํ์ฌ ๋ด๋ถ ๋ฉ์๋์ธnavigationControllerSupportedInterfaceOrientations
๋ฅผ ๊ตฌํํ์ฌ Orientation์ ์ฒซ ํ๋ฉด์์๋ง ๊ณ ์ ํ ์ ์๋๋ก ๊ตฌ์ฑํด์ฃผ์๋ค.extension MainViewController: UINavigationControllerDelegate { func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask { return navigationController.topViewController?.supportedInterfaceOrientations ?? .all } }
iOS ๊ธฐ๊ธฐ๋ ํ์ ๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ์ง๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ๋ํ๋ค. ๋ง์ฝ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ฃผ๊ณ ์ถ์ ๋ฐ์ดํฐ๊ฐ ๋ง๊ณ ๋ฐ์ดํฐ์ ์ ๋งํผ ๋ง์ ๋ทฐ๊ฐ ํ์ํ๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น? ํ๋ฉด์ ํ์ํ ์ ์๋ ๋ทฐ์ ๊ฐ์๋ ํ์ ๋์ด ์์ง๋ง ํํํด์ผํ๋ ๋ฐ์ดํฐ๊ฐ ๋ง์ ๊ฒฝ์ฐ ๋ฐ๋ณต๋ ๋ทฐ๋ฅผ ์์ฑํ๊ธฐ ๋ณด๋ค๋ ๋ทฐ๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๋ค. ์ฌ์ฉํ ์ ์๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์์์ ๋ฐ์ดํฐ์ ์๋งํผ ๋ง์ ๋ทฐ๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ง์ด ๋ญ๋นํ ์ ๋ฐ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ทฐ๋ฅผ ์ฌ์ฌ์ฉํ๋ฏ๋ก์จ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ์ฝํ๊ณ ์ฑ๋ฅ ๋ํ ํฅ์ํ ์ ์๋ค.
-
์ฌ์ฌ์ฉ์ ๋ํ์ ์ธ ์
- UITableViewCell
- UICollectionViewCell
-
์ฌ์ฌ์ฉ ์๋ฆฌ
- ํ ์ด๋ธ๋ทฐ ๋ฐ ์ปฌ๋ ์ ๋ทฐ์์ ์ ์ ํ์ํ๊ธฐ ์ํด ๋ฐ์ดํฐ ์์ค์ ๋ทฐ(์ ) ์ธ์คํด์ค๋ฅผ ์์ฒญํ๋ค.
- ๋ฐ์ดํฐ ์์ค๋ ์์ฒญ๋ง๋ค ์๋ก์ด ์ ์ ๋ง๋๋ ๋์ ์ฌ์ฌ์ฉ ํ(Reuse Queue)์ ์ฌ์ฌ์ฉ์ ์ํด ๋๊ธฐํ๊ณ ์๋ ์ ์ด ์๋์ง ํ์ธ ํ ์์ผ๋ฉด ๊ทธ ์ ์ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์ค์ ํ๊ณ ์์ผ๋ฉด ์๋ก์ด ์ ์ ์์ฑํ๋ค.
- ํ ์ด๋ธ๋ทฐ ๋ฐ ์ปฌ๋ ์ ๋ทฐ๋ ๋ฐ์ดํฐ ์์ค๊ฐ ์ ์ ๋ฐํํ๋ฉด ํ๋ฉด์ ํ์ํ๋ค
- ์ฌ์ฉ์๊ฐ ์คํฌ๋กค์ ํ๊ฒ ๋๋ฉด ์ผ๋ถ ์ ๋ค์ด ํ๋ฉด ๋ฐ์ผ๋ก ์ฌ๋ผ์ง๋ฉด์ ๋ค์ ์ฌ์ฌ์ฉ ํ์ ๋ค์ด๊ฐ๋ค.
- ์ 1๋ฒ๋ถํฐ 4๋ฒ๊น์ง์ ๊ณผ์ ์ด ๊ณ์ ๋ฐ๋ณต๋๋ค.
tableView์ ์์ฑ์ค indexPathForSelectedRow
๊ฐ ์๋๋ฐ, ์ ํ๋ row(Cell)์ indexPath๋ฅผ ๊ฐ์ ธ์ ํ์ฉํด์ค ์ ์๋ค.
var indexPathForSelectedRow: IndexPath? { get }
// ๋ด๊ฐ ์ ์ฉํ๊ณ ์ถ์ ํฐํธ ์ฌ์ด์ฆ
let fontSize = let fontSize = UIFont.systemFont(ofSize: 30)
// label์ ์๋ Text๋ฅผ NSMutableAttributedString๋ก ์ด๊ธฐํํด์ค๋ค.
guard let text = label.text else {
return
}
let attributedString = NSMutableAttributedString(string: text)
// ์์์ ๋ง๋ attributedString์ addAttribute ๋ฉ์๋๋ฅผ ํตํด Attribute๋ฅผ ์ ์ฉํด์ค๋ค.
let range = (text as NSString).range(of: prefix) // ํธ์งํ๊ณ ์ถ์ ๊ธ์์ ๋ฒ์๋ฅผ ๊ตฌํด์ค๋ค.
attributedString.addAttribute(.font, value: fontSize, range: range)
// ์ต์ข
์ ์ผ๋ก ๋ด label์ ์์ฑ์ ์ ์ฉํ๋ค.
label.attributedText = attributedString
-
์ ๋ฐฉ๋ฒ์ ์ ์ฉํ์ฌ ๋ง๋ ํจ์
func editFontSize(of prefix: String ,in label: UILabel) { guard let text = label.text else { return } let fontSize = UIFont.systemFont(ofSize: label.font.pointSize + 3) let attributedString = NSMutableAttributedString(string: text) let range = (text as NSString).range(of: prefix) attributedString.addAttribute(.font, value: fontSize, range: range) label.attributedText = attributedString }
์ฌ์ด์ฆ ์ธ์๋ ํฐํธ๋, ์์์ ๋ถ๋ถ์ ์ผ๋ก ๋ฐ๊ฟ์ค ์๋ ์๋ค.
NSForegroundColorAttributeName
NSStrokeColorAttributeName
NSUnderlineStyleAttributeName
NSBackgroundColorAttributeName
NSStrikethroughStyleAttributeName
- ํ์๊ณผ ํ์ ์ Git ์ถฉ๋ ์๋ฐฉ์ ์ํด ์คํ ๋ฆฌ๋ณด๋ ๊ด๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ํ ์ง ๊ณ ๋ฏผํ๊ณ , Storyboard Reference๋ฅผ ์ด์ฉํ์ฌ ๋ถ๋ฆฌํด์ฃผ๊ธฐ๋ก ํ์์ต๋๋ค. (One Storyboard, One ViewController)
- ์คํ ๋ฆฌ๋ณด๋ ํ์ผ ํ๊ฐ๋น ํ๊ฐ์ ViewController๋ง ์กด์ฌํ๋ฏ๋ก, ํ์ ์ ๋์ด์ ๋ค๋ฅธ ์คํ ๋ฆฌ๋ณด๋๋ฅผ ๊ฑด๋๋ฆฌ๋ ์ผ์ด ๋ฐ์ํ์ง ์๊ฒ ๋์์ต๋๋ค.
[ํ์ต ๊ธฐ๋ก ํ์ ]
JSON ํฌ๋งท์ ๋ฐ์ดํฐ์ ๋งค์นญํ ๋ชจ๋ธ ํ์ ์ ๊ตฌํํฉ๋๋ค.
- JSON ํ์ผ์ ์ดํด๋ณด๊ณ ์์ ํ๋ฉด์ ๋ณด๋ฉด์ ์ด๋ค ๋ถ๋ถ์ ํ์ ์ผ๋ก ์ค๊ณํด์ผ ํ ์ง ๊ณ ๋ฏผํด๋ณด์๋ค.
- JSON ๊ด๋ จ ํ์ ์ ์ค๊ณํ ๋ ํ๋กํผํฐ๋ฅผ ์์๊ฐ ์๋๋ผ ๋ณ์๋ก ๋ง๋๋์ง ๊ณ ๋ฏผํด๋ณด์๋ค.
- ํ์ ์ ์ค๊ณํ๋ฉด์ ๊ณ ๋ฏผํด๋ณด๋ ๋ฐ์ดํฐ๋ฅผ ๋์ฝ๋ฉ๋ง ํ๊ธฐ ๋๋ฌธ์ Codable์ด ์๋๋ผ Decodable๋ง ์ฑํํ๋๋ก ํด์ฃผ์๋ค.
- ํ์ ์์๋ JSON ๊ด๋ จ ํ์ ์ ์ค๊ณํ ๋ ์ฌ์ดํธ๋ฅผ ํ์ฉํ์ฌ ์ค๊ณํ๊ธฐ๋ ํ ๊น?
- ์ JSON ๊ด๋ จ ํ์ ์ ๋ง๋ค ๋ ํ๋กํผํฐ๋ฅผ ์์๊ฐ ์๋๋ผ๋ผ ๋ณ์๋ก ๋ง๋ค์ง?
- Codable์ ์ด์ฉํ์ฌ JSON์ ์ธ์ฝ๋ฉ, ๋์ฝ๋ฉ ํ๋ ๋ฐฉ๋ฒ
๋ฉ์ธ ํ๋ฉด, ์ถํ์ ๋ชฉ๋ก, ์ถํ์ ์์ธํ๋ฉด์ ๊ตฌํํฉ๋๋ค.
- ํ์ฑ์ ์คํจํ์์ ๋ ์ด๋ป๊ฒ ์๋ฌ์ฒ๋ฆฌ๋ฅผ ํ ์ง ๊ณ ๋ฏผํ์๋ค.
- ๊ฐ๋ฐ์์๊ฒ๋ง ๋ณด์ฌ์ค์ผ ํ ์ง, ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ค์ผ ํ ์ง ๊ณ ๋ฏผํด๋ณด์๊ณ ์ฑ์ ์ฌ์ฉํ๋ ์ฌ์ฉ์๊ฐ ์๋ฌ๋ฅผ ๋ณด๋ ๊ฒ์ด ์ ์ ํ๋ค๋ ํ๋จ์ ์ผ๋ฟ์ ๋์ฐ๋๋ก ๊ตฌ์ฑํ์๋ค.
- Navigation Bar๋ฅผ MainViewController์์๋ง ์จ๊ธธ ์ ์๋ ๋ฐฉ๋ฒ์ ๊ณ ๋ฏผํด๋ณด์๋ค.
- View Life Cycle์ ํ์ฉํ์ฌ ๋ทฐ๊ฐ ๋ณด์ฌ์ง๋ ์จ๊ธฐ๊ณ , ์ฌ๋ผ์ง๋ ๋ค์ ๋ํ๋ด๋๋ก ๊ตฌํํด๋ณด์๋ค.
- MainViewController์์ ํฌ๊ธฐ๊ฐ ๋ค๋ฅธ Label์ Text๋ถ๋ถ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ง ๊ณ ๋ฏผํด๋ณด์๋ค.
- ์คํ ๋ฆฌ ๋ณด๋์์ Label์ ์ง์ ์ถ๊ฐํ์ฌ ๊ตฌํํ ์๋ ์์์ง๋ง, ์คํ ๋ฆฌ๋ณด๋ ์์กด์ฑ์ ์ต๋ํ ๋ฎ์ถฐ๋ณด๊ธฐ ์ํด ์ฝ๋๋ฅผ ํ์ฉํ์ฌ Label์ ํ ์คํธ๋ฅผ ์ถ๊ฐํ๊ณ ์ดํ ํน์ ๊ธ์๋ง ์ฌ์ด์ฆ๊ฐ ์ปค์ง ์ ์๋๋ก ๊ตฌํํ๋ค.
- ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ๋ String์ ๋ณ์๋ก ๋ฐ๋ก ๋ด์ enumํ์ ์ผ๋ก ๋ฌถ์ด๋์ด ๋ฆฌํฉํ ๋ง์ ์งํํ๋ค.
- ์ ์ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๊ธฐ ์ํด xib๋ฅผ ํ์ฉํ์ฌ ์ปค์คํ ์ ์ ๊ตฌํํด๋ณด์๋ค.
- ์ ์ ํฐ์นํ๋ ์์ ์ ํด๋น ์ ์ ์ ๋ณด๊ฐ ๋ค์ ํ๋ฉด์ผ๋ก ์ ๋ฌ๋ ์ ์๋๋ก ๊ตฌํํ์๋ค.
- ์ ํ๋ ์
์ด ์ ํ๋ ํ์ ์ด ๋จ์์์ด ์ด๋ฅผ ์์ ๊ธฐ ์ํด ๊ณ ๋ฏผํด๋ณด์๋ค.
- delegate๋ฅผ ํ์ฉํ์ฌ ์ ์ด ๋๋ ธ์ ๋ ์์ ์ deselectํ๋๋ก ๊ตฌ์ฑํด๋ณด์๋ค.
- ResultType์ด ๊ฐ๋
์ฑ์ด ์ข๊ณ , ์๋ฌ์ ์ ์ฐํ ๋์ฒํ ์ ์๋๋ก decode ๋ฉ์๋๋ฅผ ResultType์ผ๋ก ๊ตฌํํด๋ณด์๋ค.
- fail์ ์ ํฌ๊ฐ ๋ง๋ ์๋ฌ์ description์ ์ฌ์ฉ์์๊ฒ ์๋ ค์ฃผ๊ณ success์ view๋ฅผ ๊ตฌ์ฑํ๋ ๋ฉ์๋๋ฅผ ํ๊ฒ๋ ๊ตฌ์ฑํ์๋ค.
- ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ํด๋ณด๋ ค ๋ ธ๋ ฅํ์๋๋ฐ, ์ ์ ํ๊ฒ ํ ๊ฒ์ด ๋ง์๊น?
- ๋ฐ์ดํฐ ์ ๋ฌ์ ํ ๋, ์ฆ ์ํ๊ด๋ฆฌ๋ฅผ ํ ๋ ๋จ์ํ
ํ๋กํผํฐ๋ฅผ ํ์ฉ
ํ์ฌ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ ๋ง๊ณ ๋ ์ข์ ๋ฐฉ๋ฒ์ ์๋๊ฑธ๊น? - TableView์
DataSorce
๋ฅผ ํ์ฉํ์ฌ ์ ์ ์ค์ ํ ๋ ์์ ๋ฒ์ ์ผ๋ก ์ค์ ์ ํด์ฃผ์ด์ผ ํ๋์ง ์ต์ ๋ฒ์ (iOS 14) ๋ฐฉ์์ผ๋ก ์ค์ ์ ํด์ฃผ์ด์ผํ๋์ง ์ด๋ค๊ฒ ์ ์ ํ์ง๊ฐ ์๋ฌธ์ด๋ค. - MainViewController ๋ด๋ถ์
setUpView()
๋ฉ์๋๊ฐ ๋๋ฌด ๋ง์ ์ผ์ ํ๋ ๊ฒ์ ์๋์ง?
-
์ํฉ
MainViewController๋ฅผ ์ ์ธํ ๋๋จธ์ง ๋ทฐ๋ ๋ค๋น๊ฒ์ด์ ๋ฐ๊ฐ ์กด์ฌํ๋ค. ์ฆ MainViewController๋ ๋ค๋น๊ฒ์ด์ ๋ฐ๋ฅผ ์จ๊น์ฒ๋ฆฌ ํด์ผ ํ๋ค. -
์๋
์คํ ๋ฆฌ๋ณด๋์์ ๊ฐ์ถ๊ธฐ -
์ฝ๋๋ก ๊ฐ์ถ๊ธฐ
- ๋ค๋น๊ฒ์ด์
์ปจํธ๋กค๋ฌ๋ก Embed In ๋์ด์๋ ViewController ๋ด๋ถ์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ค๋ค.
self.navigationController?.isNavigationBarHidden = true
- ๋ค๋น๊ฒ์ด์
์ปจํธ๋กค๋ฌ๋ก Embed In ๋์ด์๋ ViewController ๋ด๋ถ์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ค๋ค.
-
์ด์
์์ ๊ฐ์ ๋ฐฉ๋ฒ์ Navigation Controller์ ์ฐ๊ฒฐ๋์ด์๋ ๋ชจ๋ ViewController์ Navigation Bar๊ฐ ์จ๊ฒจ์ง๋ค. -
ํน์ ViewController์ Navigation Bar๋ฅผ ์จ๊ธฐ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ด ์๋ค.
-
ํด๊ฒฐ
ํด๋น ๋ฐฉ๋ฒ์ View Life Cycle ๋ฉ์๋๋ฅผ ํ์ฉํ์ฌ ๋ทฐ๊ฐ ํ๋ฉด์ ๋ณด์ผ ๋ Navigation Bar๋ฅผ ์จ๊ธฐ๊ณ ๋ค๋ฅธ์ฐฝ์ผ๋ก ๋์ด๊ฐ๋ ๋ค์ ๋ณด์ด๊ฒํ๋ ๋ฐฉ๋ฒ์ด๋ค.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: animated)
}
[์ ์ด Select๋์์ ๋ ๋จ๋ ํ์๋ฐฐ๊ฒฝ ์์ ๊ธฐ]
-
์ํฉ
์ ์ ํด๋ฆญํด์ ํ๋ฉด์ ํํ ๋ค์ ๋์์๋ ์ ์ ๋ฐฐ๊ฒฝ์์ด ์์์ด์ง๋ ํ์์ด ์ผ์ด๋ฌ๋ค. -
์ด์
ํ ์ด๋ธ๋ทฐ์ ์ ์ด ์ ํ๋๋ฉด ํ์์ผ๋ก ๋ณํ๊ฒ ๋๋๋ฐ, ๋ฌธ์ ๋ ์ด๋ ๊ฒ ๋ณํ ์์ด ๊ทธ๋๋ก ์ ์ง๋๋ค. -
ํด๊ฒฐ
ํ ์ด๋ธ ๋ทฐ์ ์ ์ ์ ํํ๋ฉด ํ์์ผ๋ก ๋ณํ๋ค๊ฐ ๋ค์ ์๋ ์์ผ๋ก ๋ฐ๋ก ๋์์ค๊ฒ ํ๋ ค๋ฉด ์๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ฃผ๋ฉด ๋๋ค.extension ItemListViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) } }
-
์ ์ฉํ
tableView์ ์์ฑ์ค indexPathForSelectedRow
๊ฐ ์๋๋ฐ, ์ ํ๋ row(Cell)์ indexPath๋ฅผ ๊ฐ์ ธ์ ํ์ฉํด์ค ์ ์๋ค.
var indexPathForSelectedRow: IndexPath? { get }
- performSegue์ sender๋ฅผ nil์ด ์๋๋ผ ์ ๋ฌํ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅํ
- prepare์
sender
๋ฅผ ๋ค์ด์บ์คํ ์ ํ์ฉํ์ฌ ์ ๋ฌํ ์ ์๋ค.
extension ItemListViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "ItemDetailView", sender: items[indexPath.row])
tableView.deselectRow(at: indexPath, animated: true)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let item = sender as? ExpositionItem,
let nextViewController = segue.destination as? ItemDetailViewController else {
return
}
nextViewController.item = item
}
- prepare ๋ฉ์๋ ๋ด๋ถ์์ ์ ํ๋ ์
์
indexPath
๋ฅผ ๊ตฌํด์ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ๋ ์กด์ฌํ๋ค.
extension ItemListViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "ItemDetailView", sender: nil)
tableView.deselectRow(at: indexPath, animated: true)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let indexPath = itemListTableVIew.indexPathForSelectedRow,
let nextViewController = segue.destination as? ItemDetailViewController else {
return
}
nextViewController.item = items[indexPath.row]
}
- ํ ์ด๋ธ๋ทฐ์ ์ ๋ฐ์ ์ธ ๋์ ๋ฐฉ์
- ์ฃผ์ด์ง JSON ๋ฐ์ดํฐ๋ฅผ ํ์ฑํ์ฌ ํ ์ด๋ธ๋ทฐ์ ํ์ํ๋ ๋ฐฉ๋ฒ
- ํ๋ฉด ์ ํ์ ์ ํ๋ ์ด์ ๋ฐ์ดํฐ ์ ๋ฌ ๋ฐฉ๋ฒ
- ํ ์ด๋ธ๋ทฐ์ ์ ์ ์ฌ์ฌ์ฉ ์ดํด
- ์ ์ ํ ์ ํ์ ๊ด๋ จ๋ ์์ฑ์ ์ดํด
NSMutableAttributedString
addAttribute
๋ฅผ ํ์ฉํ์ฌ ํฐํธ ์คํ์ผ์ ํธ์งํ๋ ๋ฐฉ๋ฒ- UIImage์
image
๋ฅผ ์ฝ๋๋ก ์ค์ ํ๋ ์ฌ๋ฌ๊ฐ์ง ๋ฐฉ๋ฒ - Navigation Bar item์ ๋ํ ์ดํด
- xib๋ฅผ ํ์ฉํด์ UI๋ฅผ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ
- ์คํ ๋ฆฌ๋ณด๋ ๋ถํ
- ํ ์คํธ์ฝ๋ ์๋ฌ ์์
- ํ๋ฉด๊ฐ ๋ฐ์ดํฐ ์ ๋ฌ ์ ๋ฉ์๋ ํ์ฉ
- ์คํ ์์
- ๋ฐฐ์ด์ ์ธ๋ฑ์ค๋ฅผ ์์ ํ๊ฒ ์กฐํํ๋๋ก ๊ฐ์
๋ชจ๋ ์์ดํฐ ๊ธฐ๊ธฐ์ ์ฌ๋ฌ๊ฐ์ง ์ํฉ์์๋ ์ ์์ ์ผ๋ก ํ์๋ ์ ์๋๋ก ๊ตฌํํฉ๋๋ค.
- Dynamic Type ์ธ์๋ Voice Over๋ ๊ณ ๋ คํด๋ณด์๋ค.
- Cell์ ๊ฒฝ์ฐ ์ด๋ฏธ์ง์ accessibilityLabel๊ฐ ์๋ ๊ฒฝ์ฐ ์ฝ์ง ์๊ธฐ ๋๋ฌธ์ ์ถ๊ฐํ์ฌ ์ด๋ฏธ์ง์ ์ด๋ฆ๋ ์ฝ์ ์ ์๋๋ก ์ค์ ํด์ฃผ์๋ค.
- ์ด์ ์ static ๋ฉ์๋๋ก ํ์ฉํ์๋ JSONParser ํ์
enum์ struct๋ก ๋ฐ๊พธ์ด์ฃผ์๋ค.
- static์ ๊ฒฝ์ฐ ์ฌ์ฉํ์ง ์์๋ ๋ฉ๋ชจ๋ฆฌ์ ๊ณ์ ๋จ์์๋ ๊ฒฝ์ฐ๋ฅผ ๊ณ ๋ คํ์ฌ ๋ฆฌํฉํ ๋ง ํด์ฃผ์๋ค.
- ์ต์ํ์ ์ ์ฝ์กฐ๊ฑด์ผ๋ก Auto Layout์ ๊ตฌ์ฑํ ์ ์๋๋ก ๊ณ ๋ฏผํด๋ณด์๋ค.
- ์ฒซ๋ฒ์งธ ๋ทฐ์ Orientation์ ์ธ๋ก๋ก ๊ณ ์ ํด์ฃผ๋ คํ๋๋ฐ, ํด๋น ๋ทฐ๋ง ์ธ๋ก๋ก ๊ณ ์ ์ ์ํค๊ฒ ๋๋ฉด ๊ณ ์ ์ด ๋์ง ์๋ ๋ฌธ์ ๊ฐ ์์๋ค.
- ์ด๋ ์ฒซ๋ฒ์งธ๋ทฐ์ SuperView์ธ navigation view์ orientation์ด ์ค์ ๋์ด ์์ง์์ ์๊ธฐ๋ ๋ฌธ์ ์๋ค. ๊ทธ๋์ navigation์ ๋๋ฆฌ์๋ฅผ ์ฒซ๋ฒ์งธ๋ทฐ๋ก ์ค์ ํ๊ณ navigation ์ orientation์ ์ค์ ํด์ฃผ์ด ํด๊ฒฐํ์๋ค.
- attributedText๋ฅผ ํ์ฉํ ๋ ์ ์ฉํ ๊ธ์๋ฅผ ์ ์ธํ ๋๋จธ์ง ๊ธ์๋ Dynamic Type ์ ์ฉ์ด ์ ์๋ ๊น?
- Navigation Controller๋ฅผ ํ์ฉํ์ฌ ViewController์ Oreientations์ ์ค์ ํด์ค ๋ Navigation Controller์์ ์ค์ ํด์ฃผ์ด์ผ ํ๋์ง, ์๋๋ฉด UINavigationControllerDelegate์ ์ฑํํ์ฌ ์ค์ ํด์ฃผ์ด์ผ ํ ์ง?
- button์ style ์ค์ default์ plain์ ์ ํํ ์ฐจ์ด์ ์ ์๊ณ ์ถ๋ค.
์ํฉ
๋ถ๋ถ์ ์ผ๋ก ํ ์คํธ ์คํ์ผ์ ํธ์งํด์ค Label์ด ํธ์งํด์ค ๋ถ๋ถ์ ์ ์ธํ ๋๋จธ์ง ๊ธ์๋ค์ด ์ค์๊ฐ์ผ๋ก Dynamic Type์ด ์ ์ฉ์ด ์๋๋ ํ์์ด ๋ฐ์ํ๋ค.์ด์
์๊ณ ๋ณด๋ ํธ์งํด์ค ๋ถ๋ถ(prefix)์ ์ ์ธํ ๋๋จธ์ง ๊ธ์์ ํฐํธ๋ ๊ฐ์ด ์ ์ฉํด์ค์ผ ๋ฌ๋ค.- ๋งจ ์ฒ์ ๊ธ์์ TextStyle์ด title3๋ก ์ค์ ๋์ด์๋๋ฐ addAttribute๋ฅผ ํ๋ ์๊ฐ TextStyle์ด ํ๋ฆฌ๋ ๊ฒ ๊ฐ๋ค.
ํด๊ฒฐ
๋ฐ๋ผ์ ๋๋จธ์ง ํ ์คํธ์ ๋ํด์๋ TextStyle์ ์ง์ ํด์ค ํ addAttribute ํด์ฃผ๋ ํด๊ฒฐ๋์๋ค.
์ํฉ
Dynamic Type์ ์ต๋ํ ๋๋ ธ์ ๋ ํ๋จ์ ๋ฒํผ titleLabel์ด ์ปค์ก์ง๋ง ์ด์ ๋ฐ๋ผ StackView์ ๋์ด๊ฐ ๋์ด๋์ง ์๋ ํ์์ด ๋ํ๋ฌ๋ค.์๋1
๋ ์ด์์์ด ์์กํ ์์ด์ ๊ทธ๋ฐ๊ฑด๊ฐ ์ถ์ด์ ๋ฒํผ์ ๋์ด๋ฅผ ์คํ๋ทฐ์ ๊ฐ๊ฒ ์ค์ ์ ์ฃผ์์ผ๋ ํ์์ ๋์ผํ๋ค.์๋2
๋ํ StackView์ Alignment๋ฅผ center๋ก ์ฃผ์์ ๋์๋ ์ฝ๊ฐ ๊ฒน์ณ์ง์ด ์ค๊ธด ํ์ง๋ง ๋์ผํ ๋ฌธ์ ๋ก ํด๊ฒฐ์ ๋์ง ์์๋ค.ํด๊ฒฐ
๋ฒํผ์ Style์ด ์ด์ ์ ๋ฒ์ ํธํ ๋ฌธ์ ๋ก default๋ก ๋ง์ถฐ์ ธ ์์๋๋ฐ, iOS 15๋ถํฐ ์ ์ฉ ๊ฐ๋ฅํ Plain์ผ๋ก ๋ณ๊ฒฝํด์ฃผ์ ๋ ์ด์์ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์๋ค. ๊ทธ๋ฌ๋ ์ด๋ค ์ฐจ์ด๋ก ํด๋น ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์๋์ง ์ ํํ ํ์ ์ ์ด๋ ค์ ๋ค. ๊ธฐ์กด์ Dynamic Type์ด ์ ์ฉ๋์ง ์์๋ ๋ฒํผ์ด ์ด๋ฒ์ ์ ๋ฐ์ดํธ๊ฐ ๋๋ฉด์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ฉ๋๊ฒ๋ ๋ฐ๋์๋๋ฐ ๊ทธ ๋ถ๋ถ ๋๋ฌธ์ด ์๋๊ฐ ์ถ๋ค.
์ํฉ
์ฒซ๋ฒ์งธ ๋ทฐ์ธ MainView๋ง Orientation์ ๊ณ ์ ํด์ฃผ๊ณ ์ถ์๋๋ฐ, ์ฝ๋๋ก ์ ์ฉ์ ํด์ฃผ๋ คํด๋ ๋ณํ๊ฐ ์๋ ํ์์ด ๋ํ๋ฌ๋ค.override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return .portrait }
์ด์
์ ํ๋กํผํฐ๋ฅผ overrideํ์ฌ ํ๋ฉด ๊ณ ์ ์ ํด์ฃผ๊ณ ์ถ์์ง๋ง ์ ์ฉ์ด ๋์ง์์๊ณ , ์ด์ ๋ฅผ ์ฐพ์๋ณด๋ ์ด๋ฒ ํ๋ก์ ํธ์ ๋ทฐ๋ค์ Hierarchy ์๋จ์ NavigationController๊ฐ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์๋จ ๋ทฐ์ Orientation์ด ๊ณ ์ ๋์ด์์ง ์์ ํ์ ๋ทฐ๋ค์ Orientation ๋ํ ์ ์ฉ๋์ง ์๋ ๊ฒ์ด์๋ค.ํด๊ฒฐ
Navigation์ ํด๋์ค๋ฅผ ์๋ก ์์ฑํ์ฌ Orientation์ ์ ์ฉ์์ผ์ค๊น ํ์ง๋ง, Main๋ทฐ๋ง ๊ณ ์ ์์ผ์ฃผ๊ณ ์ถ์๊ธฐ๋๋ฌธ์ ๊ตณ์ด ์์ฑ์น์๊ณ , UINavigationControllerDelegate๋ฅผ MainViewController์ ์ฑํํ์ฌ ๋ด๋ถ ๋ฉ์๋์ธnavigationControllerSupportedInterfaceOrientations
๋ฅผ ๊ตฌํํ์ฌ Orientation์ ์ฒซ ํ๋ฉด์์๋ง ๊ณ ์ ํ ์ ์๋๋ก ๊ตฌ์ฑํด์ฃผ์๋ค.extension MainViewController: UINavigationControllerDelegate { func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask { return navigationController.topViewController?.supportedInterfaceOrientations ?? .all } }
- Button์ Configuration
- Navigation Controller๋ฅผ ํ์ฉํ์ฌ Orientation ์ค์ ํ๊ธฐ
- Accessibility
- Dynamic Type
- Voice over
- static ๋ฉ์๋, static ๋ณ์์ ๋ํ ์ ํํ ๊ฐ๋
- ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ