Day 19 : challenge day

sun·2021년 9월 21일
0

100 Days of SwiftUI

목록 보기
11/11

[Day 19]

Volume Converter 깃허브 링크

@ 프로젝트 소개

  • 온도, 길이, 부피 등 하나의 단위를 정해서, 사용자로부터 값, 입력 단위, 출력 단위를 입력 받아 입력 단위의 값을 출력 단위의 값으로 바꿔주는 단위 변환기를 만드는 게 목적이다
  • 설명에 3개의 @state property 와 값을 받을 textfield , 단위를 입력받을 segmented control 2개, 그리고 결과 산출 textview 를 구현하면 된다고 되어있다!

@ 그래서 저는요...

# 기본 계획

  1. 일단 단위는 부피를 해보기로 결정했다...이유는 그나마 먹는 거랑 관련된 단위인 거 같아서ㅋㅎㅋㅎㅋㅎㅋㅎ...인터페이스 구현은 WeSplit 을 하면서 배운걸 고대로 하면 된다고 생각했고

  2. 핵심은 단위 변환 을 어떻게 하느냐 라고 생각했다!그냥 하드코딩을 해도 된다고 했지만 twostraws가 내장함수를 이용해 단위변환 하는 방법을 올려둔 만큼 이를 활용해 보기로 했다

  3. 값은 TextField 로 값 자체를 받아 VolumeAmount 에 저장하고, 입출력단위는 Picker 로 인덱스를 받아서 각각 inputUnitIndex , outputUnitIndex 에 저장한 뒤, 단위 배열에 인덱스로 접근하는 방식으로 구상했다

    @State private var inputNumber = ""
    @State private var inputUnitIdx = 0
    @State private var outputUnitIdx = 0

# Picker로 입출력 단위 받기

  1. 원래는 Measurement(value: Double, unit: Unit) 구조체를 이용해 바로 단위만 나타낼 수 있을 줄 알고
  1. 입출력 단위를 받는 부분에서 Measurement 오브젝트 들을 담고 있는 unitConvert 배열에 접근하게 해서 inputUnit, outputUnitMeasurment 오브젝트 를 바로 저장하게 했는데

  2. 단위만 출력하는 게 불가능해서 단위 이름을 담은 문자열 배열 units 를 따로 선언해서 인터페이스에는 해당 배열에 접근해 단위만 출력되도록 했다

  3. 나중에 변환값을 연산하는 프로퍼티를 만들면서 헷갈리기도 하고 바꾼 이름이 더 적합하다고 생각해 바꿔줬다

    let units = ["mL", "L", "cup", "gal"]
    let unitVolume = [UnitVolume.milliliters, .liters, .cups, .gallons]
    
    ...
    
    Section(header: Text("Input Unit")) {
        Picker(selection: $inputUnitIdx, label: Text("Input Unit")) {
            ForEach(0 ..< units.count) {
                Text("\(self.units[$0])")
            }
        }
        .pickerStyle(SegmentedPickerStyle())
    }

# 변환값 연산 프로퍼티 convertedNumber

  1. Measurement(value: Double, unit: Unit) 구조체를 선언하기 위해 inputUnitIdx , outputUnitIdx 를 활용해 unitVolume 배열에서 입력받은 단위와 일치하는 UnitVolumeinputVolumeoutputVolume 에 저장하고

  2. inputVolumeMeasurement 구조체 의 오브젝트로 선언한 뒤

  3. converted 메서드 를 사용해서 변환된 값을 outputVolume 에 할당하고 이를 리턴해서 convertedNumber 에 저장했다

  4. 지금와서 보니 convertedNumber 의 타입을 Double 로 선언하고 outputVolume.value 를 리턴했어도 될 것 같다

    var convertedNumber : Measurement<UnitVolume> {
        let volumeAmount = Double(inputNumber) ?? 0
        let inputUnit = unitVolume[inputUnitIdx]  // 1번 과정
        let outputUnit = unitVolume[outputUnitIdx]  // 1번 과정
        
        let inputVolume = Measurement(value: volumeAmount, unit: inputUnit)  // 2번 과정
        let outputVolume = inputVolume.converted(to: outputUnit)  // 3번 과정
        
        return outputVolume
    }

# 결과 출력

  1. 처음에는 별 생각없이 Text("\(convertedNumber)") 로 출력했는데 소수점 밑 자리를 자르려고 했더니 위의 방식으로는 바로 고칠 수가 없었다

  2. convertedNumber.value, convertedNumber.unit 으로 나눠서 출력해보려고 했는데 후자의 경우 단위만 출력되는 게 아니고 타입이 같이 출력됐다

  3. 결국 값은 converteNumber.value 를 이용해서 출력하고, 타입은 Picker 에서와 같이 unit 배열을 통해 해결했다

    Section(header: Text("Result")) {
        Text("\(convertedNumber.value, specifier: "%.2f") \(self.units[outputUnitIdx])")
    }

☀️ TIL

  • Picker 로 사용자로부터 입력을 받을 때 ForEach 를 통해 단순히 숫자를 입력받더라도 배열 을 활용해 다양한 결과를 산출할 수 있다
  • 배열에 UnitVolume 타입들을 저장하고 입력값에 따라 입력된 타입을 불러와 별도의 변수에 저장해 다른 타입의 오브젝트 선언에 활용할 수 있다
profile
☀️

0개의 댓글