๐Ÿฅ Sparta_iOS_4๊ธฐ/4๏ธโƒฃ 240701_๊ณ„์‚ฐ๊ธฐ ์•ฑ ver.2

[์ฝ”๋“œ๋ฒ ์ด์ŠคUI] iOS ์ž…๋ฌธ ๊ฐœ์ธ๊ณผ์ œ_๊ฐ„๋‹จํ•œ ๊ณ„์‚ฐ๊ธฐ ์•ฑ ๋งŒ๋“ค๊ธฐ 4 ~ 6๋‹จ๊ณ„

AHN.Jihyeon 2024. 7. 1. 21:05

Lev.4 ์ˆซ์ž๋ฒ„ํŠผ๊ณผ ์—ฐ์‚ฐ ๋ฒ„ํŠผ์˜ ์ƒ‰์ƒ ๊ตฌ๋ถ„ํ•˜๊ธฐ

 

 

 

๋ฐœ์ƒํ•œ ์˜ค๋ฅ˜

 

์˜ค๋ฅ˜ ์„ค๋ช…

Thread 1: Fatal error: Can't form a Character from a String containing more than one extended grapheme cluster

 

์ด ์˜ค๋ฅ˜๋Š” ์ฃผ์–ด์ง„ ๋ฌธ์ž์—ด์ด ํ•˜๋‚˜์˜ Character๋กœ ํ‘œํ˜„๋  ์ˆ˜ ์—†์„ ๋•Œ ๋ฐœ์ƒํ•œ๋‹ค.

Swift์—์„œ Character๋Š” ํ•˜๋‚˜์˜ ํ™•์žฅ๋œ ์ž๋ชจ ํด๋Ÿฌ์Šคํ„ฐ(Extended Grapheme Cluster)๋กœ ์ •์˜๋œ๋‹ค.

ํ™•์žฅ๋œ ์ž๋ชจ ํด๋Ÿฌ์Šคํ„ฐ๋Š” ํ•˜๋‚˜์˜ ๋ฌธ์ž๋กœ ์ธ์‹๋˜๋Š” ๋‹จ์ผ ์œ ๋‹ˆ์ฝ”๋“œ ์‹œํ€€์Šค๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

 

์ฆ‰, “AC”๊ฐ€ ํ•˜๋‚˜์˜ ๋ฌธ์ž๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฐœ์ƒํ•œ ์˜ค๋ฅ˜์˜€๋‹ค. 

 

 

 

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

buttonNums ๋ฌธ์ž์—ด ๋ฐฐ์—ด์— ์žˆ๋Š” ์š”์†Œ๋“ค์„ ๋ฐ˜๋ณต๋ฌธ์„ ํ†ตํ•ด

์ •์ˆ˜๋กœ ๋ณ€ํ™˜์ด ๋˜๋ฉด ์ƒ‰์ƒ์„ ๋ฐ”๊ฟ”์ฃผ๊ณ , ์ •์ˆ˜๋กœ ๋ณ€ํ™˜์ด ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด(nil)

์ƒ‰์ƒ์„ ๋ณ€๊ฒฝํ•ด์ฃผ๋Š” ์กฐ๊ฑด๋ฌธ ์ž‘์„ฑ.

 

 

 

 

์ œ์ถœ ์ฝ”๋“œ

import UIKit
import SnapKit

class ViewController: UIViewController {
    
    var viewNum = 0
    
    var numLabel = UILabel()
    let buttonNums = ["7", "8", "9", "+",
                      "4", "5", "6", "-",
                      "1", "2", "3", "×",
                      "AC", "0", "=", "÷"]
    
    
    //horizontalStackView ํด๋กœ์ € ์‚ฌ์šฉ
    private func horizontalStackView(_ buttons: [UIButton])-> UIStackView {
        let stackView = UIStackView(arrangedSubviews: buttons)
        stackView.axis = .horizontal
        stackView.backgroundColor = .black
        stackView.spacing = 10
        stackView.distribution = .fillEqually
        return stackView
    }
    
    var verticalStackView: UIStackView = {
        let stackView = UIStackView()
        stackView.axis = .vertical
        stackView.backgroundColor = .black
        stackView.spacing = 10
        stackView.distribution = .fillEqually
        return stackView
    }()
    
    
    //๋ฒ„ํŠผ ํ•œ์ค„์„ ๋งŒ๋“ค์–ด์„œ horizontalStackView์— ๋„ฃ์–ด์ฃผ๋Š” ํ•จ์ˆ˜
    private func makeNumButton(buttonNums: [String]) {
        var buttonArray: [UIButton] = []
        
        for num in buttonNums {
            let button = UIButton()
            if Int(num) != nil {
                button.backgroundColor = UIColor(red: 58/255, green: 58/255, blue: 58/255, alpha: 1.0)
            } else{
                button.backgroundColor = .orange
            }
            button.setTitle(num, for: .normal)
            button.titleLabel?.font = .boldSystemFont(ofSize: 30)
            button.layer.cornerRadius = 40
            
            buttonArray.append(button)
            
            if buttonArray.count == 4 {
                verticalStackView.addArrangedSubview(horizontalStackView(buttonArray))
                buttonArray = []
            }
        }
    }
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureUI()
        makeNumButton(buttonNums: buttonNums)
    }
    
    
    
    func configureUI(){
        //์†์„ฑ
        view.backgroundColor = .black
        
        numLabel.backgroundColor = .black
        numLabel.textColor = .white
        numLabel.text = "\(viewNum)"
        numLabel.textAlignment = .right
        numLabel.font = .boldSystemFont(ofSize: 60)
        
        //view์—
        [numLabel, verticalStackView].forEach{view.addSubview($0)}
        
        
        //AutoLayout
        numLabel.snp.makeConstraints {
            $0.leading.trailing.equalToSuperview().inset(30)
            $0.top.equalToSuperview().offset(200)
        }
        
        verticalStackView.snp.makeConstraints {
            $0.height.equalTo(350)
            $0.width.equalTo(350)
            $0.top.equalTo(numLabel.snp.bottom).offset(60)
            $0.centerX.equalToSuperview()
        }
        
    }
    
    
}

#Preview{
    let preview = ViewController()
    return preview
}

 

 

 

 

lev.5 ๋Š” ๋ฒ„ํŠผ์„ ์›ํ˜•์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๊ฒƒ์œผ๋กœ

button.layer.cornerRadius = 40

์ด๋ฏธ ์•ž์˜ ๋‹จ๊ณ„์—์„œ ํ•ด๊ฒฐ ์™„๋ฃŒ.

 

 


Lev.6 ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๋ผ๋ฒจ์— ํ‘œ์‹œ๋˜๊ฒŒ ํ•˜๊ธฐ_์ˆซ์ž๊ฐ€ 0์œผ๋กœ ์‹œ์ž‘ํ•˜์ง€ ์•Š๊ฒŒ ํ•˜๊ธฐ. 

 

๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ํ•ด๋‹น ๋ฒ„ํŠผ์˜ ํƒ€์ดํ‹€ num์„ 

์–ด๋–ป๊ฒŒ label.text์— ๋„ฃ๋Š”์ง€์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์ด ์ •๋ง ๋งŽ์•˜๋‹ค. 

 

๋ฒ„ํŠผ์ด ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— numButtonTapped() ํ•จ์ˆ˜๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์„œ

๋ฒ„ํŠผ์ด ๋ˆŒ๋ ธ์„ ๋•Œ ๊ฐ๊ฐ์˜ ๋ฒ„ํŠผ์˜ ํƒ€์ดํ‹€์„ ๋ผ๋ฒจ์— ๋„ฃ๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ๋‹ค.

 

์ด ๊ณผ์ • ์ค‘์—์„œ ๋‹ค๋ฅธ ๋ถ„๋“ค๊ป˜ ์งˆ๋ฌธํ•˜๋ฉด์„œ ์ด ํ•จ์ˆ˜์— ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ UIButton์„ ๋ฐ›๊ณ 

currntTitle์„ ์‚ฌ์šฉํ•ด ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ํžŒํŠธ๋ฅผ ์–ป์—ˆ๋‹ค. 

String? ํƒ€์ž…์œผ๋กœ ์‚ฌ์šฉ ์‹œ ์–ธ๋žฉํ•‘์„ ํ•ด์ฃผ์–ด์•ผ ํ–ˆ๋‹ค.

 

 

 

 

๋ฐœ์ƒํ•œ ์˜ค๋ฅ˜

์—ฌ๊ธฐ์„œ numButtonTapped(sender: UIButton) ํ•จ์ˆ˜์—์„œ UIButton์ด ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ

์–ด๋–ป๊ฒŒ ์ „๋‹ฌ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š”์ง€ ์˜๋ฌธ์ด ์ƒ๊ฒผ๋‹ค.

 

 

numButtonTapped(sender: UIButton) ํ•จ์ˆ˜์—์„œ UIButton์€

makeNumButton(buttonNums: [String]) ํ•จ์ˆ˜ ๋‚ด์—์„œ ์ƒ์„ฑ๋œ ๋ฒ„ํŠผ๋“ค์ด

addTarget ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ํ˜ธ์ถœ๋˜์—ˆ์„ ๋•Œ ์ „๋‹ฌ๋œ๋‹ค. 

 

addTarget ๋ฉ”์„œ๋“œ๋Š” ๋ฒ„ํŠผ์ด ํ„ฐ์น˜๋˜๋ฉด ํ•ด๋‹น ๋ฒ„ํŠผ ๊ฐ์ฒด(sender)๋ฅผ

numButtonTapped ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•œ๋‹ค.

 

 

 

ํ•˜์ง€๋งŒ, ์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•  ์‹œ ์•ฑ์ด ์ž‘๋™์ด ๋˜์ง€ ์•Š์•˜๋‹ค.

viewNum์€ numLable์—์„œ 0์œผ๋กœ ๋ณด์ด๊ธฐ ์œ„ํ•ด

์ „์—ญ ๋ณ€์ˆ˜๋กœ ์ดˆ๊ธฐ๊ฐ’์„ "0"์œผ๋กœ ์„ธํŒ…ํ–ˆ์—ˆ๋‹ค.

 

์ด viewNum์— ์ž…๋ ฅ๋œ ๋ฌธ์ž์—ด์˜ ์ฒซ๋ฒˆ์งธ ์ธ๋ฑ์Šค๊ฐ€ "0"์ด ์•„๋‹ˆ๋ผ๋ฉด

์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ๋ฐ›์€ userInput์„ ์ถ”๊ฐ€ํ•ด์ฃผ๊ณ ,

"0"์ด๋ผ๋ฉด ์ฒซ๋ฒˆ์งธ ์ธ๋ฑ์Šค๋ฅผ ์ œ๊ฑฐํ•ด์ฃผ๊ณ  userInput์„ ์ถ”๊ฐ€ํ•ด์คฌ์–ด์•ผ ํ–ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๊ทธ ๋ถ€๋ถ„์ด ๋น ์ ธ์„œ, "0"์ผ ๋•Œ ์ด๋ฅผ ์ œ๊ฑฐํ•˜๋‹ˆ nil๋กœ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค. 

 

 

 

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

์ด๋ ‡๊ฒŒ ์ˆ˜์ •ํ•˜๋‹ˆ ์ž‘๋™์ด ๋˜์—ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ตณ์ด ์ธ๋ฑ์Šค๋กœ ์ ‘๊ทผํ•˜์ง€ ์•Š์•„๋„ ๋น„๊ต๋ฅผ ์ˆ˜ ์žˆ์—ˆ๋‹ค. 

 

 

 

์ œ์ถœ ์ฝ”๋“œ

//
//  ViewController.swift
//  calculatorApp
//
//  Created by ahnzihyeon on 6/26/24.
//

import UIKit
import SnapKit

class ViewController: UIViewController {
    var viewNum = "0"
    var numLabel = UILabel()
    let buttonNums = ["7", "8", "9", "+",
                      "4", "5", "6", "-",
                      "1", "2", "3", "×",
                      "AC", "0", "=", "÷"]
    
    
    //horizontalStackView ํด๋กœ์ € ์‚ฌ์šฉ
    private func horizontalStackView(_ buttons: [UIButton])-> UIStackView {
        let stackView = UIStackView(arrangedSubviews: buttons)
        stackView.axis = .horizontal
        stackView.backgroundColor = .black
        stackView.spacing = 10
        stackView.distribution = .fillEqually
        return stackView
    }
    
    var verticalStackView: UIStackView = {
        let stackView = UIStackView()
        stackView.axis = .vertical
        stackView.backgroundColor = .black
        stackView.spacing = 10
        stackView.distribution = .fillEqually
        return stackView
    }()
    
    
    //๋ฒ„ํŠผ ํ•œ์ค„์„ ๋งŒ๋“ค์–ด์„œ horizontalStackView์— ๋„ฃ์–ด์ฃผ๋Š” ํ•จ์ˆ˜
    private func makeNumButton(buttonNums: [String]) {
        var buttonArray: [UIButton] = []
        
        for num in buttonNums {
            let button = UIButton()
            if Int(num) != nil {
                button.backgroundColor = UIColor(red: 58/255, green: 58/255, blue: 58/255, alpha: 1.0)
            } else{
                button.backgroundColor = .orange
            }
            button.setTitle(num, for: .normal)
            button.titleLabel?.font = .boldSystemFont(ofSize: 30)
            button.layer.cornerRadius = 40
            buttonArray.append(button)
            
            if buttonArray.count == 4 {
                verticalStackView.addArrangedSubview(horizontalStackView(buttonArray))
                buttonArray = []
            }
            
            button.addTarget(self, action: #selector(numButtonTapped), for: .touchDown)
        }
    }
    
    @objc
    private func numButtonTapped(sender: UIButton) {
        
        var userInput = sender.currentTitle!
        
        if numLabel.text == "0" {
            viewNum.removeFirst()
            viewNum += userInput
        } else {
            viewNum += userInput
        }
        numLabel.text = viewNum
    }
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureUI()
        makeNumButton(buttonNums: buttonNums)
    }
    
    
    
    func configureUI(){
        //์†์„ฑ
        view.backgroundColor = .black
        
        numLabel.text = "0"
        numLabel.backgroundColor = .black
        numLabel.textColor = .white
        numLabel.textAlignment = .right
        numLabel.font = .boldSystemFont(ofSize: 60)
        numLabel.adjustsFontSizeToFitWidth = true //label ์‚ฌ์ด์ฆˆ์— ๋งž๊ฒŒ ํฐํŠธ ํฌ๊ธฐ ์ž๋™ ์กฐ์ ˆ
        
        
        //view์—
        [numLabel, verticalStackView].forEach{view.addSubview($0)}
        
        
        //AutoLayout
        numLabel.snp.makeConstraints {
            $0.leading.trailing.equalToSuperview().inset(30)
            $0.top.equalToSuperview().offset(200)
        }
        
        verticalStackView.snp.makeConstraints {
            $0.height.equalTo(350)
            $0.width.equalTo(350)
            $0.top.equalTo(numLabel.snp.bottom).offset(60)
            $0.centerX.equalToSuperview()
        }
    }
    
    
}

#Preview{
    let preview = ViewController()
    return preview
}