์ค๋์ ์ด์ ํ๋ ์์ดํฐ ์ค์ ๊ธฐ๋ณธ ์ฑ์ ํด๋ก ํ๋ ๊ฒ์ ์์ฑํ์๋ค.
์ด์ ํ๋ ์๋ณด๋ค ์ค๋ ํ๊ฒ ํจ์ฌ ๋ง์์ ์ด๋์๋ถํฐ ์ ๋ฆฌํด์ผ ํ ์ง ๋ชจ๋ฅด๊ฒ ๋ค...
๊ผผ๊ผผํ๊ฒ ๋ค ์ ๋ฆฌํ๊ณ ์ถ์๋ฐ ๊ทธ๋ฌ๊ธฐ์
๊ฐ์ ๋ฃ๊ธฐ & ํ๊ธฐ & ์ค์ต ๋ฐ๋ผํ๊ธฐ & ๋ธ๋ก๊ทธ ๊ธ ์ ๋ฆฌ 4๊ฐ์ง๋ฅผ ํ๊บผ๋ฒ์ ํด์ผ๋ผ์ ๋ถ๊ฐ^^
์ผ๋จ ๊ธฐ์ต๋๋๋๋ก ์ ์ด๋ด์ผ์ง.. (๊ตฌํ ์์์ ์๊ด X)
1. Navigation Controller ์ถ๊ฐ
๋จผ์ ์๋ ์ค์ ์ฑ์์ ๋ค๋น๊ฒ์ด์ ๋ฐ ๋ถ๋ถ์ ๋ณด๋ฉด
์ ๋ ๊ฒ ์คํฌ๋กค์ ์ฌ๋ฆฌ๋ฉด "์ค์ "์ด๋ผ๊ณ ์ ํ์๋ ๋ถ๋ถ์ด ํฐ ํ์ดํ์์ ๋ค๋น๊ฒ์ด์ ๋ฐ ์์ชฝ ํ์ดํ๋ก ๋์ด๊ฐ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
๋ด๊ฐ ํด๋ก ํ ์ฑ์์๋ ๋ง์ฐฌ๊ฐ์ง๋ก ์ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ ์ ํ๋ค.
๊ทธ๋ด๋ ค๋ฉด ๋จผ์ ์ด๋ ๊ฒ ์คํ ๋ฆฌ๋ณด๋์ ๋ค๋น๊ฒ์ด์ ์ปจํธ๋กค๋ฌ๋ฅผ ์ถ๊ฐํด์ ์ฐ๊ฒฐํด๋๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด ViewController์์ ์ ๊ทผํด์ title์ ๋ง์๋๋ก ์์ ํ ์ ์๋ค.
override func viewDidLoad() {
super.viewDidLoad()
// .. ์๋ต
self.title = "Settings"
}
์ด๋ ๊ฒ ViewController์ viewDidLoad() ํจ์์ ํ์ดํ์ ์ง์ ํด ๋์ผ๋ฉด ๋๋ค.
๊ทผ๋ฐ ์ด๋ ๊ฒ๋ง ํ๋ฉด ๋งจ ์ฒ์์ ํฐ ๊ธ์จ๋ก ๋์ค๋ LargeTitle์ด ๋์ค์ง ์๊ณ ๊ทธ๋ฅ ๋ค๋น๊ฒ์ด์ ๋ฐ ์ค์์ ์๊ฒ ํ์ดํ๋ง ํ์๋๋ค.
๋งจ ์ฒ์ ์์งค์ฒ๋ผ ์ฒ์์ ํฐ ํ์ดํ์ด ๋์๋ค๊ฐ ์คํฌ๋กคํ๋ฉด ์์ ํ์ดํ๋ก ์ฌ๋ผ์ก๋ค๊ฐ ๋ค์ ๋ํ๋ฌ๋ค๊ฐ ๊ทธ๋ ๊ฒ ํ๋ ค๋ฉด
๋ค๋ฅธ ์ฝ๋ ์์ ์ด ํ์ํ๋ค.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.prefersLargeTitles = true
}
viewWillAppear() ์ด๋ผ๋ ํจ์๋ ๋ทฐ๊ฐ ๋ํ๋ ๋๋ง๋ค ํธ์ถ๋๋ ํจ์์ด๋ค.
(didLoad๋ ๋ฉ์ธ ํ๋ฉด์ ๊ฒฝ์ฐ ํ๋ฒ ํธ์ถ๋๊ณ ๋๋ฉด ๋)
์ฌ๊ธฐ์ ์์ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ prefersLargeTitles ๊ฐ์ true๋ก ๋ง๋ค์ด์ฃผ๋ฉด ๋ทฐ๊ฐ ์คํ๋ ๋๋ง๋ค ํฐ ํ์ดํ์ด ๋ณด์ฌ์ง๋ค.
2. Model ์์ฑ ๋ฐ ๋ทฐ๋ฆฌ์คํธ ๋ด์ฉ ์ถ๊ฐ
์ด์ ๋ง๋ค์๋ ๋ชจ์ต์๋ label์ ์๋ฌด ๋ด์ฉ๋ ๋ค์ด๊ฐ ์์ง๊ฐ ์์์๋ค.
๊ฑฐ๊ธฐ์ ๋ด์ฉ์ ์ฑ์์ผ ํ๋๋ฐ ์ด๋ฅผ ์ํด ๋จผ์ Model์ ๋ง๋ค์๋ค.
์ผ๋ฐ swiftํ์ผ๋ก SettingModel.swift๋ฅผ ์๋์ ๊ฐ์ด ๊ตฌํํ๋ค.
import Foundation
struct SettingModel {
var leftImageName: String = ""
var menuTitle: String = ""
var subTitle: String?
var rightImageName: String?
}
๊ทธ๋ฅ ๋จ์ํ struct๋ก ๊ฐ๊ฐ ์ด๋ฏธ์ง ๋ถ๋ถ๊ณผ ๋ ์ด๋ธ๋ถ๋ถ์ ๋ํ ๊ฐ์ ์ ์ฅํ String๋ค์ ๋ง๋ค์๋ค.
๊ทธ๋ฆฌ๊ณ ViewController์์ ์๋์ ๊ฐ์ด ๊ตฌํํ๋ค.
var settingModel = [[SettingModel]]() //2์ค ๋ฐฐ์ด
@IBOutlet weak var settingTableView: UITableView!
func makeData() {
settingModel.append([SettingModel(leftImageName: "person.circle", menuTitle: "Sign in to your iPhone", subTitle: "Set up iCloud, the App Store, and more.", rightImageName: nil)])
settingModel.append([SettingModel(leftImageName: "gear", menuTitle: "General", subTitle: nil, rightImageName: "chevron.right"),
SettingModel(leftImageName: "person.fill", menuTitle: "Accessibility", subTitle: nil, rightImageName: "chevron.right"),
SettingModel(leftImageName: "hand.raised.fill", menuTitle: "Privacy", subTitle: nil, rightImageName: "chevron.right")])
}
์ค์ ํ๋ฉด์์ ๋ณด์ด๋ ๋ฐ์ ๊ฐ์ด ๊ฐ๊ฐ ์์๋ค์ด ์น์ ์ด ๋๋์ด์ ธ ์๋ค.
์ฒซ๋ฒ์งธ ์น์ ์๋ 1๊ฐ์ง cell, ๋๋ฒ์งธ ์น์ ์๋ 3๊ฐ์ง cell๋ค์ด ์๋ค.
๊ทธ๋์ 2์ค ๋ฐฐ์ด์ ํ๋ ๋ง๋ค์ด์ ๊ฑฐ๊ธฐ์ ์์๋ค์ ๋ฃ๋๋ค.
์ฌ๊ธฐ์ ์ด๋ฏธ์ง ํ์ผ๋ค์ apple ์์คํ ์์ ์ ๊ณตํ๋ SF Symbols์ ์๋ ์์คํ ์ด๋ฆ์ด๋ค.
์ด๋ ๊ฒ ํ๊ณ Delegate์์ ํจ์๋ฅผ ์์ ํ๋ค.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return settingModel[section].count
}
func numberOfSections(in tableView: UITableView) -> Int {
return settingModel.count
}
์ฒซ๋ฒ์งธ ํจ์๋ numberOfRowsInSection์ผ๋ก ๊ฐ ์น์ ์ ๋ช๊ฐ์ ํ์ด ์๋์ง ๋ฐํํด์ฃผ๋ ํจ์๊ณ
๋๋ฒ์งธ ํจ์๋ ์น์ ์ ์๊ฐ ๋ช๊ฐ ์ง ๋ฐํํด์ค๋ค.
๊ทธ๋ฆฌ๊ณ ๊ฐ๊ฐ์ cell์ ๋ค์ด๊ฐ ๋ด์ฉ๋ค์ ์ ๋ฌํ๊ธฐ ์ํ ํจ์์ด๋ค.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileCell", for: indexPath) as! ProfileCell
cell.topTitle.text = settingModel[indexPath.section][indexPath.row].menuTitle
cell.profileImageView.image = UIImage(systemName: settingModel[indexPath.section][indexPath.row].leftImageName)
cell.bottomDescription.text = settingModel[indexPath.section][indexPath.row].subTitle
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "MenuCell", for: indexPath) as! MenuCell
cell.leftImageView.image = UIImage(systemName: settingModel[indexPath.section][indexPath.row].leftImageName)
cell.middleTitle.text = settingModel[indexPath.section][indexPath.row].menuTitle
cell.rightImageView.image = UIImage(systemName: settingModel[indexPath.section][indexPath.row].rightImageName ?? "")
cell.rightImageView.tintColor = .lightGray
return cell
}
์ฒซ๋ฒ์งธ ํ์ ๋์ค๋ profile์ ๋ฐ์ ๋ค๋ฅธ cell๋ค๊ณผ ๋ค๋ฅธ ๋ชจ์ต์ด๊ธฐ ๋๋ฌธ์ if ๋ฌธ์ผ๋ก ์น์ ์ ๋๋์ด์ ๊ฐ๊ฐ ์ค์ ํด์ฃผ๊ณ
ํ์ํ๋ค๋ฉด ์์๋ ์ค์ ํด์ค๋ค.
3. General ์ค์
(ํ ๋ค ๋ ๋ผ๊ฐ๋ค.. ใ ใ ... ๊ฑฐ์ ๋ค์จ์ ์๋ฃ๋ง ๋๋ฅด๋ฉด ๋์๋๋ฐ... ๋์๊ฐ ๋์ ์ผ๋๋ฐ.. ๋ค์..์จ์ผ์ง...)
์ด์ ์ฒ์ ๋ณด์ด๋ ํ๋ฉด์ ๋ํ ๊ตฌ์ฑ์ ๋ง์ณค๊ณ , General(์ผ๋ฐ) ์ค์ ์ ์ ๋๋ ์ ๋ ๋์ค๋ ํ๋ฉด์ ๋ํ ๊ตฌ์ฑ์ ํ๋ค.
์ด๋ ๊ฒ ๋ณด๋ฉด ์ผ๋ฐ์ ๋๋ ์ ๋ ๋ค๋ฅธ ํ ์ด๋ธ๋ทฐ ํ๋ฉด์ผ๋ก ๋์ด๊ฐ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ผ๋ฐ ์ค์ ํ ์ด๋ธ ๋ทฐ์ ์ ๋ค์ ๋ ์ด๋ธ ํ๊ฐ์ ์ด๋ฏธ์ง ๋ทฐ ํ๊ฐ๋ก ๊ตฌ์ฑ๋ผ์๊ณ ,
๋๊ฐ์ด ๋ค๋น๊ฒ์ด์ ๋ฐ๊ฐ ์๋ค.
๋ณด์ด๋ ๊ฑฐ๋ ๋๊ฐ์ด ๋ง๋ค์ด๋ดค๋ค.
๊ทผ๋ฐ ์ด๋ฒ์ ๋ค๋ฅธ ๋์ ๊ฐ์ด Cell, Struct(Model), Controller์ ํ์ผ๋ค์ ๋ฐ๋ก ๊ตฌ์ฑํ์ง ์๊ณ
GeneralViewController์์ ๋ค๊ฐ์ด ํ๊บผ๋ฒ์ ์ฝ๋ฉํ๋ค.
์ด๋ ๊ฒ ํ๋ฉด ์ ์ง๋ณด์๋ฅผ ํ๊ฑฐ๋, ์ฝ๋๊ฐ ๊ธธ์ด์ง๊ณ ๋ณต์กํด์ง๋ฉด ์ข์ง ์์ ๋ฐฉ๋ฒ์ธ๋ฐ
์ง๊ธ์ ์์ฒญ ๋จ์ํ๊ธฐ๋ ํ๊ณ ์ฝ๋๊ฐ ๊ธธ์ง๋ ์์์ ์ด ๋ฐฉ๋ฒ๋ ๊ฐ์์์ ๊ฐ๋ฅด์ณ์คฌ๋ค.
์ผ๋จ ์คํ ๋ฆฌ๋ณด๋์์ ๋ณด๋ฉด ์ด๋ ๊ฒ ์๊ฒผ๋ค.
Cell์ ๋ฐ๋ก ์ง์ ํ์ง ์๊ณ
ํ ์ด๋ธ ๋ทฐ ์์ Table View Cell ์ค๋ธ์ ํธ๋ฅผ ์ง์ ๋ฃ์ด์ ๋ง๋ค์๋ค.
๋ทฐ ์ด๋ฆ์ GeneralViewController ์ด๋ค.
GeneralViewController.swift์ ์ฝ๋๋ฅผ ๋ณด๋ฉด
import UIKit
class GeneralCell: UITableViewCell {
@IBOutlet weak var leftLabel: UILabel!
@IBOutlet weak var rightImageView: UIImageView! {
didSet{
rightImageView.image = UIImage.init(systemName: "chevron.right")
}
}
}
struct GeneralModel {
var leftTitle: String = ""
}
๋จผ์ TableView์ ๋ํ ํด๋์ค GeneralCell์ ์ ์ธํ๊ณ ๊ทธ ์์ ๊ตฌ์ฑ์์๋ค์ ์์๋ ์ผ๋ก ๊ฐ์ ธ์จ๋ค.
์ฌ๊ธฐ์ rightImageView๋ ๋ชจ๋ ๋์ผํ๊ฒ ์ค๋ฅธ์ชฝ ๋ฐฉํฅ ๊บพ์ ์์ด์ฝ์ด๋ฏ๋ก didSet์ ์ด์ฉํ์ฌ ๋ฏธ๋ฆฌ ์ค์ ์ ํด ๋๋๋ค.
๊ทธ๋ฆฌ๊ณ struct๋ก ๋ชจ๋ธ์ ์ ์ธํ๋ค.
rightImageView์ ๋ํ ์ค์ ์ ์ด๋ฏธ ๋ง์ณค์ผ๋ฏ๋ก ๋๋จธ์ง ๊ตฌ์ฑ์์์ธ leftLabel์ ๋ํด ์์๋ฅผ ์ ์ธํ๋ค.
class GeneralViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var model = [[GeneralModel]]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return model[section].count
}
func numberOfSections(in tableView: UITableView) -> Int {
return model.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "GeneralCell", for: indexPath) as! GeneralCell
cell.leftLabel.text = model[indexPath.section][indexPath.row].leftTitle
cell.rightImageView.tintColor = .lightGray
return cell
}
๊ทธ ๋ค์์ผ๋ก TableView์ ๋ํ ํด๋์ค๋ฅผ ์ ์ธํ๋ค.
Model๋ก 2์ค ๋ฐฐ์ด์ ๋ง๋ค๊ณ ๊ฐ ์์น์ ๋ํด ์ค์ ํ๋ค.
@IBOutlet weak var generalTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
generalTableView.delegate = self
generalTableView.dataSource = self
self.title = "General"
self.navigationController?.navigationBar.prefersLargeTitles = false
model.append([GeneralModel(leftTitle: "About")])
model.append([GeneralModel(leftTitle: "Keyboard"),
GeneralModel(leftTitle: "Game Controller"),
GeneralModel(leftTitle: "Fonts"),
GeneralModel(leftTitle: "Language & Region"),
GeneralModel(leftTitle: "Dictionary")])
model.append([GeneralModel(leftTitle: "Reset")])
self.view.backgroundColor = UIColor(white: 245/255, alpha: 1)
generalTableView.backgroundColor = UIColor(white: 245/255, alpha: 1)
}
}
๋ง์ง๋ง์ผ๋ก viewDidLoad์์ Model์ ์์๋ค์ ๋ด์ฉ์ ์ ์ฅํด์ฃผ๊ณ ๋ฐฐ์ด์ ์ ์ฅํ๋ค.
๋, ๋ค๋น๊ฒ์ด์ ๋ฐ์ ํ์ดํ๋ฑ์ ์ค์ ํด์ค๋ค.
์ด์ ViewController์์ ์๋์ ๊ฐ์ด ๋ค๋น๊ฒ์ด์ ์ปจํธ๋กค๋ฌ๊น์ง ํด์ ์ฐ๊ฒฐํด์ฃผ๋ฉด
if indexPath.section == 1 && indexPath.row == 0 {
if let generalVC = UIStoryboard(name: "GeneralViewController", bundle: nil).instantiateViewController(withIdentifier: "GeneralViewController") as? GeneralViewController {
self.navigationController?.pushViewController(generalVC, animated: true)
}
}
4. Profile ์ค์
ํ๋กํ์ผ ๋ถ๋ถ์ ์ด๋ ๊ฒ ๋ง๋๋ ๊ฒ์ด ๋ชฉํ์ด๋ค.
๊ณ ๋ คํด์ผํ ์ฌํญ์
1. ํ ์ด๋ธ๋ทฐ๊ฐ ์๋๋ค.
2. ํ๋ฉด์ด ์๋์์ ์๋ก ์ฌ๋ผ์จ๋ค.
3. ์ด๋ฉ์ผ์ ์ ๋ ฅํ์ง ์์์๋๋ Next(๋ค์) ๋ฒํผ์ด ํ์ฑํ ๋์ง์๋๋ค.
์ ๋์ด๋ค.
๋จผ์ MyIDViewController๋ผ๋ ์ด๋ฆ์ผ๋ก swift์ xibํ์ผ์ ๋ง๋ค๊ณ
์คํ ๋ฆฌ๋ณด๋์์ ์ด์ฌํ ๋ทฐ์ ๋ชจ์ต์ ์นดํผํ๋ค.
๊ทธ๋ฆฌ๊ณ MyIDViewController.swift์์ ๋ทฐ์ ๊ตฌ์ฑ์์๋ค์ ์์๋ ์ผ๋ก ๊ฐ์ ธ์ค๊ฑฐ๋ ์ก์ ์ผ๋ก ๊ฐ์ ธ์์
์ผ์ ์ํํ ์ ์๋๋ก ์ฝ๋ฉํ๋ค.
import UIKit
class MyIDViewController: UIViewController {
@IBOutlet weak var nextBtn: UIButton!{
didSet{
nextBtn.isEnabled = false
}
}
@IBOutlet weak var emailTextField: UITextField!
@IBAction func doCancel(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
@IBOutlet weak var cancelBtn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
emailTextField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
// textFieldDidChange(sender: emailTextField)
}
@objc func textFieldDidChange(sender: UITextField){
if sender.text?.isEmpty == true {
nextBtn.isEnabled = false
} else {
nextBtn.isEnabled = true
}
}
}
๊ฐ์ ธ์ฌ ์์๋ ์ด ์ธ๊ฐ์ง์ด๋ค.
Cancel ๋ฒํผ, Next ๋ฒํผ, Email์ ๋ ฅ ํ ์คํธ ํ๋.
Cancel ๋ฒํผ์ ๋๋ฆฌ๋ฉด dismiss ๋๋๋ก ์ค์ ํ๊ณ ,
EmailTextField์ Next ๋ฒํผ์ ๋ํด์๋ ์ด๋ฉ์ผ ํ๋ ์์ ๊ธ์๊ฐ ์์ ๋ Next ๋ฒํผ์ ํ์ฑํ ์ํค๊ณ , ์์ผ๋ฉด ๋นํ์ฑํ ์ํค๋ ์ก์ ์ ์ํํ๋๋ก ํ๋ค. ๊ทธ์ ๋ํ ํจ์๊ฐ textFieldDidChangeํจ์์ด๋ค.
๊ทธ๋ฆฌ๊ณ ์ด์ ๋ง์ฐฌ๊ฐ์ง๋ก ViewController์์ ํ๋กํ์ผ ๋ถ๋ถ์ ๋๋ ์ ๋ ํ๋ฉด์ด ๋์ด๊ฐ๋๋ก
์ฐ๊ฒฐํด์ฃผ์ด์ผ ํ๋ค.
if indexPath.section == 0 && indexPath.row == 0 {
let myidVC = MyIDViewController(nibName: "MyIDViewController", bundle: nil)
self.present(myidVC, animated: true, completion: nil)
}
์ด๋ ๊ฒ ์ฐ๊ฒฐํ๋ค.
์ฌ๊ธฐ์ ์ฃผ์ํ ์ ์ด ์๋ค.
๋ค๋ฅธ ํ๋ฉด๋ค์ ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ์ผ๋ก ํ๋ฉด์ด ๋ํ๋ฌ๋๋ฐ ์ด๋ฒ์๋ ๋ชจ๋ฌ์ฒ๋ผ ์๋์์ ์๋ก ๋ํ๋๊ฒ ํด์ผํ๋ค.
๊ทธ๋์ present๋ผ๋ ๋ฉ์๋๋ฅผ ์ด์ฉํด์ ํ๋ฉด์ด ๋์ด๊ฐ๊ฒ ํ๊ณ ์๋ค.
์ด๋ ๊ฒ ํด์ ์์ดํฐ setting app clone ์ค์ต์ด ๋๋ฌ๋ค ^_^
Reference
https://www.inflearn.com/course/uikit-ios14/dashboard
UIKit - iOS14 ์ค๋ฌด ๊ฐ์ด๋ <iOS์ฑ ์ง์ง ๊ฐ๋ฐ์ ๋๊ธฐ> - ์ธํ๋ฐ | ๊ฐ์
UIKit - iOS14 ์ค๋ฌด ์ฑ ๊ฐ์ด๋ ์ ๋ฌธ์๋ฅผ ์ํ ๊ธฐ์ด๋ถํฐ ํํํ ์ค๋ช ์ ์ค๋นํ์ต๋๋ค. ๊ฒฝ๋ ฅ์๋ค๋ ๋์น๊ธฐ ์ฌ์ด ๊ฐ๋ ๋ค์ ํ์คํ๊ฒ ์ก์๋๋ฆฝ๋๋ค. ์ค๋ฌด์์ ๋ง๋ค์ด์ง๋ ์ฑ์ ํ์คํ๊ฒ ๋ฐฐ์ธ ์ ์๋๋ก
www.inflearn.com
'๐ก work work work > swift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
swift ์ค์ต - 5 : Photo Gallery App (0) | 2022.02.22 |
---|---|
swift ์ค์ต - 4 : OnBoardingView (0) | 2022.02.21 |
swift ์ค์ต - 3.1 : Setting App Clone (0) | 2022.02.14 |
swift ์ค์ต - 2 : Dispatch Queue (0) | 2022.02.14 |
swift ์ค์ต - 1 : Passing Data (0) | 2022.02.09 |
๋๊ธ