아침에 branch 삭제하고 다시 시작했다..
근데 그 와중에 git add를 HOME 디렉터리에 해버려서.. (어이가 없음..)
git status를 했는데 홈 디렉터리에 있는 파일들이 빨간 글씨로 나오고,
Changes not staged for commit
다른 거 커밋하려고 하면 계속 오류가 뜨고, git restore이나 git clean 같은 거도 써 봤는데 소용없었음..
계속 오류를 해결하려고 해 봤는데 안 돼서 결국 튜터님을 찾아갔음..
git rm -rf .git
하니까 다 사라지고 해결됨..
본격적으로 과제로 돌아가자면
//PaymentViewController.swift
import UIKit
class PaymentViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var things: [Any] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return things.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "paymentCell", for: indexPath) as! PaymentTableViewCell
if let thing = things[indexPath.row] as? IceCream {
// ice cream
cell.payNameLabel.text = thing.koreanName
cell.payPriceLabel.text = "\(thing.price)원"
var flavorText = ""
for flavor in thing.flavor {
flavorText += "\(flavor.name), "
}
cell.payDetailLabel.text = flavorText
if let firstFlavorImage = thing.flavor.first?.image {
cell.payImageView.image = firstFlavorImage
} else {
cell.payImageView.image = nil
}
} else if let thing = things[indexPath.row] as? Coffee {
// coffee
cell.payNameLabel.text = thing.koreanName
cell.payPriceLabel.text = "\(thing.price)원"
cell.payImageView.image = nil
} else if let thing = things[indexPath.row] as? Cake {
// cake
cell.payNameLabel.text = thing.koreanName
cell.payPriceLabel.text = "\(thing.price)원"
cell.payImageView.image = nil
} else if let thing = things[indexPath.row] as? Beverage {
//beverage
cell.payNameLabel.text = thing.koreanName
cell.payPriceLabel.text = "\(thing.price)원"
cell.payImageView.image = nil
}
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
things.append(
IceCream(koreanName: "파인트",
EnglishName: "pint",
choice: 3,
flavor: [
Flavor(name: "바닐라", image: UIImage(named: "Vanilla")!),
Flavor(name: "월넛", image: UIImage(named:"Walnut")!)],
price: 452,
image: UIImage(named: "Vanilla")!,
isCorn: true))
tableView.delegate = self
tableView.dataSource = self
let nibName = UINib(nibName: "paymentCell", bundle: nil)
tableView.register(nibName, forCellReuseIdentifier: "paymentCell")
tableView.reloadData()
}
}
var things: [Any] = []
우선 데이터를 담아줄 배열을 만든다.
원래 AnyObject 타입을 새로 만들어서 배열을 담기로 했는데, 에러가 떠서 Any로 바꿨다.
override func viewDidLoad() {
super.viewDidLoad()
things.append(
IceCream(koreanName: "파인트",
EnglishName: "pint",
choice: 3,
flavor: [
Flavor(name: "바닐라", image: UIImage(named: "Vanilla")!),
Flavor(name: "월넛", image: UIImage(named: "Walnut")!)],
price: 452,
image: UIImage(named: "Vanilla")!,
isCorn: true))
tableView.delegate = self
tableView.dataSource = self
let nibName = UINib(nibName: "paymentCell", bundle: nil)
tableView.register(nibName, forCellReuseIdentifier: "paymentCell")
tableView.reloadData()
}
만약에 things 배열에 IceCream 저 데이터가 전달되었다는 가정하에
if let thing = things[indexPath.row] as? IceCream {
// ice cream
//이름
cell.payNameLabel.text = thing.koreanName
//가격
cell.payPriceLabel.text = "\(thing.price)원"
//맛
var flavorText = ""
for flavor in thing.flavor {
flavorText += "\(flavor.name), "
}
cell.payDetailLabel.text = flavorText
//이미지
if let firstFlavorImage = thing.flavor.first?.image {
cell.payImageView.image = firstFlavorImage
} else {
cell.payImageView.image = nil
}
}
커피나 다른 것들도 이런 식으로 if let thing = things[indexPath.row] as? Cake
이런 식으로 만약에 things에 있는 값이 Cake 면 그에 맞는 코드를 실행하도록 한다.
그런데 실행해 보면
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
이런 오류가 발생하는 데 왜일까..
밑에 보면 _SkinRabbins/ScenceDelegate.swift:20: Fatal error: Unexpectedly found nil while unwrapping an Optional value라고 적혀있는데 이걸로 어디에서 에러가 났는지 알 수 있다. SceneDelegate.swift 에 20번째 줄을 보면 되는데,
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIStoryboard(name: "PaymentStoryboard", bundle: nil).instantiateInitialViewController()
self.window = window
window.makeKeyAndVisible()
}
여기 연결된 스토리보드가 다른 거여서 났던 오류였다.
이런 방식으로 오류를 하나하나 잡다 보니 테이블뷰를 만들 수 있었음!
최종 코드
//PaymentViewController.swift
import UIKit
class PaymentViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var things: [Any] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return things.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "paymentCell", for: indexPath) as! PaymentTableViewCell
cell.payNameLabel.font = UIFont.boldSystemFont(ofSize: 14)
cell.payPriceLabel.font = UIFont.boldSystemFont(ofSize: 14)
if let thing = things[indexPath.row] as? IceCream {
// ice cream
cell.payNameLabel.text = thing.koreanName
cell.payPriceLabel.text = "\(thing.price)원"
var flavorText = ""
for (index, flavor) in thing.flavor.enumerated() {
flavorText += flavor.name
if index < thing.flavor.count - 1 {
flavorText += ", "
}
}
cell.payDetailLabel.text = flavorText
if let firstFlavorImage = thing.flavor.first?.image {
cell.payImageView.image = firstFlavorImage
} else {
cell.payImageView.image = nil
}
} else if let thing = things[indexPath.row] as? Coffee {
// coffee
cell.payNameLabel.text = thing.koreanName
cell.payPriceLabel.text = "\(thing.price)원"
cell.payImageView.image = nil
} else if let thing = things[indexPath.row] as? Cake {
// cake
cell.payNameLabel.text = thing.koreanName
cell.payPriceLabel.text = "\(thing.price)원"
cell.payImageView.image = nil
} else if let thing = things[indexPath.row] as? Beverage {
//beverage
cell.payNameLabel.text = thing.koreanName
cell.payPriceLabel.text = "\(thing.price)원"
cell.payImageView.image = nil
}
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
things.append(
IceCream(koreanName: "파인트",
EnglishName: "pint",
choice: 3,
flavor: [
Flavor(name: "바닐라", image: UIImage(named: "Vanilla")!),
Flavor(name: "월넛", image: UIImage(named:"Walnut")!)],
price: 452,
image: UIImage(named: "Vanilla")!,
isCorn: true))
things.append(
IceCream(koreanName: "패밀리",
EnglishName: "family",
choice: 4,
flavor: [
Flavor(name: "망고 탱고", image: UIImage(named: "Mango Tango")!),
Flavor(name: "뉴욕 치즈케이크", image: UIImage(named:"New York CheeseCake")!)],
price: 452,
image: UIImage(named: "New York CheeseCake")!,
isCorn: true))
tableView.delegate = self
tableView.dataSource = self
let nibName = UINib(nibName: "PaymentTableViewCell", bundle: Bundle(for: type(of: self)))
tableView.register(nibName, forCellReuseIdentifier: "paymentCell")
tableView.reloadData()
}
}
git에 지금까지 한 것들 올려놓고, 이제 버튼을 추가해 보자
이 버튼을 추가할 것이다. 우선 디자인은 신경 쓰지 않고,
이렇게 버튼과 레이블로 구성함
import UIKit
class PaymentTableViewCell: UITableViewCell {
//테이블 뷰 셀 구성
@IBOutlet weak var payImageView: UIImageView!
@IBOutlet weak var payNameLabel: UILabel!
@IBOutlet weak var payDetailLabel: UILabel!
@IBOutlet weak var payPriceLabel: UILabel!
//버튼
@IBOutlet weak var minusButton: UIButton!
@IBOutlet weak var plusButton: UIButton!
@IBOutlet weak var cntLabel: UILabel!
var minusButtonAction: (() -> Void)?
var plusButtonAction: (() -> Void)?
var cnt: Int = 1 {
didSet {
cntLabel.text = "\(cnt)"
minusButton.isEnabled = cnt > 1
minusButton.tintColor = cnt > 1 ? .black : .gray
}
}
@IBAction func plusTapped(_ sender: Any) {
plusButtonAction?()
updatePriceLabel()
}
@IBAction func minusTapped(_ sender: Any) {
minusButtonAction?()
updatePriceLabel()
}
var thingPrice:Int = 0 //thing.price 값 저장
private func updatePriceLabel() {
let totalPrice = cnt * thingPrice // 현재 수량과 thingPrice 값을 곱해서 총 가격 계산
payPriceLabel.text = "\(totalPrice)원" // 가격 레이블 업데이트
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
잘 연결해 주고, 코드는 이렇게
//PaymentViewController.swift에 테이블 뷰 아이스크림일 경우 셀 부분
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "paymentCell", for: indexPath) as! PaymentTableViewCell
cell.payNameLabel.font = UIFont.boldSystemFont(ofSize: 14)
cell.payPriceLabel.font = UIFont.boldSystemFont(ofSize: 14)
cell.plusButton.tintColor = .black
cell.minusButton.tintColor = .gray
if let iceCream = things[indexPath.row] as? IceCream {
cell.thingPrice = iceCream.price // thingPrice 값을 iceCream.price로 설정
} else if let coffee = things[indexPath.row] as? Coffee {
cell.thingPrice = coffee.price // thingPrice 값을 coffee.price로 설정
} else if let cake = things[indexPath.row] as? Cake {
cell.thingPrice = cake.price // thingPrice 값을 cake.price로 설정
} else if let beverage = things[indexPath.row] as? Beverage {
cell.thingPrice = beverage.price // thingPrice 값을 beverage.price로 설정
}
// ice cream
if let thing = things[indexPath.row] as? IceCream {
// 이름
cell.payNameLabel.text = thing.koreanName
// 가격
cell.payPriceLabel.text = "\(thing.price)원"
// 선택한 맛
var flavorText = ""
for (index, flavor) in thing.flavor.enumerated() {
flavorText += flavor.name
if index < thing.flavor.count - 1 {
flavorText += ", "
}
}
cell.payDetailLabel.text = flavorText
//이미지
if let firstFlavorImage = thing.flavor.first?.image {
cell.payImageView.image = firstFlavorImage
} else {
cell.payImageView.image = nil
}
//버튼
cell.minusButtonAction = {
if cell.cnt > 1 { cell.cnt -= 1 }
}
cell.plusButtonAction = {
cell.cnt += 1
}
}
기본이 1개로 되어있고, 1개일 경우 마이너스 버튼은 클릭할 수 없음!
그리고 플러스를 누르면 값이 그만큼 증가하는 것을 볼 수 있다ㅏ
이건 PaymentViewController.swift 전체 코드
import UIKit
class PaymentViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var things: [Any] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return things.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "paymentCell", for: indexPath) as! PaymentTableViewCell
cell.payNameLabel.font = UIFont.boldSystemFont(ofSize: 14)
cell.payPriceLabel.font = UIFont.boldSystemFont(ofSize: 14)
cell.plusButton.tintColor = .black
cell.minusButton.tintColor = .gray
if let iceCream = things[indexPath.row] as? IceCream {
cell.thingPrice = iceCream.price // thingPrice 값을 iceCream.price로 설정
} else if let coffee = things[indexPath.row] as? Coffee {
cell.thingPrice = coffee.price // thingPrice 값을 coffee.price로 설정
} else if let cake = things[indexPath.row] as? Cake {
cell.thingPrice = cake.price // thingPrice 값을 cake.price로 설정
} else if let beverage = things[indexPath.row] as? Beverage {
cell.thingPrice = beverage.price // thingPrice 값을 beverage.price로 설정
}
// ice cream
if let thing = things[indexPath.row] as? IceCream {
// 이름
cell.payNameLabel.text = thing.koreanName
// 가격
cell.payPriceLabel.text = "\(thing.price)원"
// 선택한 맛
var flavorText = ""
for (index, flavor) in thing.flavor.enumerated() {
flavorText += flavor.name
if index < thing.flavor.count - 1 {
flavorText += ", "
}
}
cell.payDetailLabel.text = flavorText
//이미지
if let firstFlavorImage = thing.flavor.first?.image {
cell.payImageView.image = firstFlavorImage
} else {
cell.payImageView.image = nil
}
//버튼
cell.minusButtonAction = {
if cell.cnt > 1 { cell.cnt -= 1 }
}
cell.plusButtonAction = {
cell.cnt += 1
}
} else if let thing = things[indexPath.row] as? Coffee {
// coffee
cell.payNameLabel.text = thing.koreanName
cell.payPriceLabel.text = "\(thing.price)원"
cell.payImageView.image = nil
} else if let thing = things[indexPath.row] as? Cake {
// cake
cell.payNameLabel.text = thing.koreanName
cell.payPriceLabel.text = "\(thing.price)원"
cell.payImageView.image = nil
} else if let thing = things[indexPath.row] as? Beverage {
//beverage
cell.payNameLabel.text = thing.koreanName
cell.payPriceLabel.text = "\(thing.price)원"
cell.payImageView.image = nil
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
tableView.deselectRow(at: indexPath, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
things.append(
IceCream(koreanName: "파인트",
EnglishName: "pint",
choice: 3,
flavor: [
Flavor(name: "바닐라", image: UIImage(named: "Vanilla")!),
Flavor(name: "월넛", image: UIImage(named:"Walnut")!)],
price: 452,
image: UIImage(named: "Vanilla")!,
isCorn: true))
things.append(
IceCream(koreanName: "패밀리",
EnglishName: "family",
choice: 4,
flavor: [
Flavor(name: "망고 탱고", image: UIImage(named: "Mango Tango")!),
Flavor(name: "뉴욕 치즈케이크", image: UIImage(named:"New York CheeseCake")!)],
price: 452,
image: UIImage(named: "New York CheeseCake")!,
isCorn: true))
tableView.delegate = self
tableView.dataSource = self
let nibName = UINib(nibName: "PaymentTableViewCell", bundle: Bundle(for: type(of: self)))
tableView.register(nibName, forCellReuseIdentifier: "paymentCell")
tableView.reloadData()
}
}
현재 Ice cream 외에는 사진에 관련한 데이터가 없어서 적용은 못하고 있음
또 깃에 업로드해놓고,,
오른쪽에 x 버튼 누르면 삭제하기 만들기
여기서 오른쪽 상단에 있는 x 버튼을 구현할 것임
//셀 삭제 "X" 버튼
var deleteButtonAction: (() -> Void)?
@IBAction func xTapped(_ sender: Any) {
deleteButtonAction?()
}
버튼 추가해서 연결해 주고,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "paymentCell", for: indexPath) as! PaymentTableViewCell
//셀 삭제
cell.deleteButtonAction = { [weak self] in
self?.deleteThing(at: indexPath) // 셀 삭제 메서드 호출
}
이렇게 셀 삭제해 주는데, 메서드는
//셀 삭제 메서드
private func deleteThing(at indexPath: IndexPath) {
things.remove(at: indexPath.row) // 데이터 배열에서 해당 항목 삭제
tableView.deleteRows(at: [indexPath], with: .left) // 테이블 뷰에서 해당 셀 삭제
}
이렇게 만들어주면 끝!
잘 삭제되는 화면을 볼 수 있다!
근데 이거 만들고 시도해 보니까 모든 셀을 삭제했을 때 어떻게 할 지도 생각해야겠다.. ㅠ
이제 하단에 Footer를 만들어서 총금액과 결제하기, 취소하기 버튼 구현
FooterView 까지 구현했다 !
그런데 몇 가지 해결해야 할 문제점이 있다..
1 FooterView 가 살짝 떠있음 ㅠ
2 장바구니가 비어있습니다. 만들어야 함
셀을 전부 삭제 했을 경우
취소하기 버튼을 눌렀을 경우
결제 alert 창에서 예를 선택했을 경우
3 셀 삭제 시 총 금액 줄어드는 거 에러있는 것 같음
ㄴ 아닌가..
4 셀에 cntLabel 증가 감소해도 총 금액이 안 변함
5. 맛 세부 정보 표시하는 거 길면 ... 이 뜬다..