TIL

27일차 TIL

h_luz 2024. 4. 3. 21:30

 

아침에 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 까지 구현했다 !

 

 

그런데 몇 가지 해결해야 할 문제점이 있다..

 

FooterView 가 살짝 떠있음 ㅠ 

 

2 장바구니가 비어있습니다. 만들어야 함

       셀을 전부 삭제 했을 경우

       취소하기 버튼을 눌렀을 경우

       결제 alert 창에서 예를 선택했을 경우

 

3 셀 삭제 시 총 금액 줄어드는 거 에러있는 것 같음

   ㄴ 아닌가..

 

4 셀에 cntLabel 증가 감소해도 총 금액이 안 변함

 

5. 맛 세부 정보 표시하는 거 길면 ... 이 뜬다..

'TIL' 카테고리의 다른 글

29일차 TIL  (2) 2024.04.05
28일차 TIL  (1) 2024.04.04
26일차 TIL  (2) 2024.04.02
25일차 TIL  (0) 2024.04.01
24일차 TIL  (2) 2024.03.29