이제 Git으로 push, pull, merge하는 과정은 완전히 익숙해진 것 같다!
자꾸 생기는 UserInterfaceState.xcuserstate 파일 변경은 그냥 git stash 해버리면 되는 것....😮💨
팀원들에게도 이제 알려줄 수 있을 정도로 이해한 것 같아 뿌듯하다.
오늘은 내가 담당하는 장바구니 화면 레이아웃 잡고 수량 조절 및 삭제 로직 짜는 것까지 구현했다.
🪄 주문 내역 페이지 요구사항
- 총 주문 메뉴 개수를 표시
- 주문한 메뉴 표시 → 테이블 뷰 활용
- 각 메뉴를 표시하며 메뉴 옆에 +, - 버튼을 만들어서 해당 메뉴의 수량을 조절
- 주문 메뉴 전체를 취소하는 취소하기 버튼을 구현
- 주문 메뉴 전체를 결제하는 결제하기 버튼을 구현
UI 구성
어제 미처 작업하지 못한 오토레이아웃 작업을 했다.
전에는 오토레이아웃 작업이 너무 어려웠는데 이제는 그래도 몇 번 해봤다고 조금은 감이 오는 것 같기도~?
그리고 오늘 한 번 파일을 잘못 건들고 날아가서 레이아웃을 다시 잡으면서 점점 더 익숙해진 것 같다..ㅋㅋ
변경 사항 커밋을 꼭 자주 하자..!!!!!!
데이터 출력
1) 임시 OrderArray 데이터 설정
struct OrderMenu {
var menu: MenuItem
var quantity: Int
}
// 임시 주문 배열 넘어왔다고 가정
var orderArray:[OrderMenu] = [
OrderMenu(menu: baconCheese, quantity: 2),
OrderMenu(menu: cheese, quantity: 3),
OrderMenu(menu: doubleBacon, quantity: 5)
]
이전 페이지에서 주문 목록 데이터가 넘어왔다고 가정하고 orderArray를 생성했다.
2) TableViewDataSource 메서드 구현
extension CartViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.orderArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = orderListTableView.dequeueReusableCell(withIdentifier: "CartTableViewCell", for: indexPath) as? CartTableViewCell else { return UITableViewCell() }
let order = orderArray[indexPath.row]
let price = order.menu.price*order.quantity
cell.orderMenuLabel.text = order.menu.name
cell.orderCountLabel.text = "\(order.quantity)"
cell.orderPriceLabel.text = "₩" + String(price)
// 셀의 스텝퍼 초기 값을 주문 수량으로 설정
cell.countStepper.value = Double(order.quantity)
return cell
}
}
테이블 뷰의 데이터 출력되는 메서드 구현하는 과정이다.
이 때 각 셀의 라벨의 text뿐만 아니라 스텝퍼 초기 값을 주문 수량으로 설정하기!도 잊지 말기
스탭퍼의 초기값을 설정해주지 않으면 앱을 실행하고 가장 초기에 스탭퍼의 수량 변경이 마음대로 조작되지 않기 때문!
메뉴 수량 조절
1) stepperValueChanged() : 주문 수량 업데이트
@IBOutlet weak var countStepper: UIStepper!
var updateQuantityHandler: ((Int) -> Void)?
override func awakeFromNib() {
// print("CartTableViewCell - awakeFromNib() called")
super.awakeFromNib()
self.selectionStyle = .none
countStepper.addTarget(self, action: #selector(stepperValueChanged), for: .valueChanged)
countStepper.minimumValue = 1
}
@objc func stepperValueChanged() {
// 스텝퍼의 값이 변경되면 호출되는 메소드
// 라벨의 텍스트를 스텝퍼의 값으로 업데이트
let value = Int(countStepper.value)
updateQuantityHandler?(value)
}
stepperValueChanged 메서드는 스텝퍼를 통해 수량이 변경될 때 호출되는 메서드이다.
이때 updateQuantityHandler 클로저를 호출하여 주문 수량이 변경되었음을 뷰 컨트롤러에 알린다!
뷰 컨트롤러는 이 정보를 사용하여 해당 주문의 수량을 업데이트하고 화면을 새로고침할 수 있다.
이제 그 과정을 작성해보자!
2) cellForRowAt에서 quantityUpdateHandler 클로저를 설정 -> 주문 수량 업데이트
// 수량 업데이트
cell.updateQuantityHandler = { [weak self] quantity in
guard let self = self else { return }
// 주문 수량 업데이트
self.orderArray[indexPath.row].quantity = quantity
// 가격 업데이트
let newPrice = order.menu.price * quantity
// cell의 수량 및 가격 설정하기
cell.updatePriceLabel(newPrice: newPrice, quantity: quantity)
print("스텝퍼 수정: \(orderArray)")
self.updateTotal()
}
updateQuantityHandler는 주문 수량이 변경될 때마다 실행되는 클로저이다.
이 클로저가 호출되며 주문의 수량을 업데이트하고 새로운 가격을 계산하여 화면에 반영할 수 있도록 한다.
3) updatePriceLabel()
func updatePriceLabel(newPrice: Int, quantity: Int) {
orderPriceLabel.text = "₩" + String(newPrice)
orderCountLabel.text = "\(quantity)"
}
위의 코드는 updateQuantityHandler안에서 호출되는updatePriceLabel 메서드의 내용이다.
화면에 주문 수량과 가격을 업데이트 해주기 위한 메서드이다.
👉 이렇게 진행해줬다면 스텝퍼로 값이 변경될 때마다 orderArray의 값이 변경되고 변경된 값이 화면에 잘 뿌려지는 것을 확인할 수 있을 것이다. 이제 총 주문 개수와 총 가격을 출력해보자!
총 주문 개수 및 가격 표시
1) updateTotal() 총 가격 설정 메서드
func updateTotal() {
var totalCount = 0
var totalPrice = 0
for order in orderArray {
totalCount += order.quantity
totalPrice += (order.menu.price) * (order.quantity)
}
orderTotalCount.text = "\(totalCount)"
orderTotalPrice.text = "₩\(totalPrice)"
}
orderArray인 주문 배열의 모든 주문 항목을 순회하면서 총 주문 수량과 주문 가격을 계산하고 화면에 업데이트 해주는 메서드이다.
처음 뷰가 로드될 때, 데이터가 수정이 되었을 때 등 필요한 시점에 해당 메서드를 호출해주면 된다!
셀 삭제 기능
1) cell 삭제: UITableViewDelegate
- 셀을 옆으로 스와이프해서 삭제
- Edit Mode 활용하여 구현
// MARK: - cell 삭제
// 셀 편집 여부를 설정
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
// 사용자가 셀을 삭제할 때 호출됩니다.
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// 삭제하려는 셀의 인덱스
let index = indexPath.row
// 데이터 소스에서 셀 삭제
orderArray.remove(at: index)
// 테이블 뷰에서 셀 삭제
tableView.deleteRows(at: [indexPath], with: .automatic)
updateTotal()
}
}
}
canEditRowAt 메서드를 사용하여 각 셀을 편집 가능하게 만들고 그런 다음, 사용자가 삭제를 확정할 때 호출되는 commit editingStyle 메서드를 구현했다. 셀을 삭제했을 땐 해당 셀의 데이터가 orderArray에서도 제거되고, 테이블 뷰에서도 셀이 삭제된다.
그리고 삭제된 셀을 제외한 나머지 주문 정보들로부터 다시 총 가격을 계산하여 업데이트 한다.
2) 전체 삭제 버튼 Alert Action
- 전체 삭제 버튼을 눌렀을 때 모든 주문을 삭제하고 총 가격 업데이트
// MARK: - 전체 삭제 버튼
@IBAction func tapDeleteButton(_ sender: UIButton) {
let alert = UIAlertController(title: nil, message: "장바구니를 비우시겠습니까?", preferredStyle: .alert)
// 확인 액션(삭제)
let delete = UIAlertAction(title: "확인", style: .default) { (_) in
// 주문 배열 비우기
self.orderArray.removeAll()
// 테이블 뷰 리로드
self.orderListTableView.reloadData()
// 총 가격 업데이트
self.updateTotal()
print(self.orderArray)
}
let cancel = UIAlertAction(title: "취소", style: .cancel)
alert.addAction(delete)
alert.addAction(cancel)
self.present(alert, animated: true, completion: nil)
}
위 코드에서는 확인 액션을 선택하면 주문 배열을 비우고 테이블뷰를 리로드하여 모든 셀을 삭제하도록 구현했다.
알림창은 UIAlertAction을 사용했고 다시 updateTotal 메서드를 호출해서 총 가격을 업데이트 해주기!
3) 결제하기 버튼 Alert Action
- 결제하기 버튼을 누르면 주문이 완료되고 장바구니가 비워지며, 사용자에게 알림이 표시
// MARK: - 결제하기 버튼
@IBAction func tapPaymentButton(_ sender: UIButton) {
let alert = UIAlertController(title: nil, message: "결제하시겠습니까?", preferredStyle: .alert)
// 확인 액션
let confirmAction = UIAlertAction(title: "확인", style: .default) { (_) in
// 주문을 결제하고 장바구니 비우기
self.orderArray.removeAll()
// 테이블 뷰 리로드
self.orderListTableView.reloadData()
// 총 가격 업데이트
self.updateTotal()
// 결제 완료 알림창 표시
let paymentCompletedAlert = UIAlertController(title: "결제 완료", message: "주문이 성공적으로 결제되었습니다.", preferredStyle: .alert)
let okAction = UIAlertAction(title: "확인", style: .default, handler: nil)
paymentCompletedAlert.addAction(okAction)
self.present(paymentCompletedAlert, animated: true, completion: nil)
}
// 취소 액션
let cancelAction = UIAlertAction(title: "취소", style: .cancel)
// 알림창에 액션 추가
alert.addAction(cancelAction)
alert.addAction(confirmAction)
// 알림창 표시
self.present(alert, animated: true, completion: nil)
}
전체 취소 버튼과 동일하게 UIAlertAction사용해서 알림창 표시되도록 구현했다.
이렇게 하면 요구사항은 전부 적용되었다. .🥹
시연 화면
순서대로 화면 첨부했다.
수량 변경 ➡️ 셀 삭제 및 전체 삭제 ➡️ 결제하기 버튼 이벤트
💬 느낀 점
push전 commit 여러번 하기 (작업한 내용 실수해도 복구할 수 있도록..!🥹)
전에 과제로 했던 투두리스트 앱과 굉장히 비슷해서 로직 짜는 과정을 더 재밌게 작업할 수 있었다.
깃, 오토레이아웃, 테이블 뷰 모두 역시 할수록 실력이 조금씩 늘고 있는 것 같다.
'TIL✏️' 카테고리의 다른 글
[iOS] WishList App - CoreData 사용하기 (2) | 2024.04.17 |
---|---|
[iOS] WishList App - URLSession 으로 API 연결하기 (2) | 2024.04.16 |
[iOS] 키오스크 앱 프로젝트 - 스토리보드 초기 뷰 컨트롤러 설정 (1) | 2024.04.02 |
[iOS] 키오스크 앱 프로젝트 - GitHub 초기 작업 (1) | 2024.04.02 |
[iOS] 키오스크 앱 프로젝트 - CollectionView 공부 (1) | 2024.04.02 |