[ swift ] 섭씨/화씨 변환 기능 구현과 트러블슈팅

sonny·2025년 1월 13일
0

TIL

목록 보기
101/140

온도 변환 로직 (SettingsManager)

SettingsManager는 온도 변환 및 사용자 설정값을 관리한다.

온도 변환 공식은 태어나서 처음 봣는데 아래와 같다.

  • 섭씨 → 화씨: ( F = C \times \frac{9}{5} + 32 )
  • 화씨 → 섭씨: ( C = (F - 32) \times \frac{5}{9} )

코드

static func convertTemperature(value: Double, to unit: TempUnit) -> Double {
    switch unit {
    case .celsius:
        return (value - 32) * 5.0 / 9.0
    case .fahrenheit:
        return (value * 9.0 / 5.0) + 32
    }
}

그리고 UserDefaults를 이용해 사용자의 온도 단위 선택값을 저장/불러오는 기능을 제공할 수 있다.

static func saveTempUnit(_ unit: TempUnit) {
    UserDefaults.standard.set(unit.rawValue, forKey: tempUnitKey)
}

static func getTempUnit() -> TempUnit {
    let value = UserDefaults.standard.string(forKey: tempUnitKey) ?? TempUnit.celsius.rawValue
    return TempUnit(rawValue: value) ?? .celsius
}

설정 메뉴에서 단위 전환 (WeatherViewController)

WeatherViewController에서는 UIMenu를 활용해 설정 메뉴를 구현해주고

메뉴에서 단위를 선택하면 Bool값을 이용해 isCelsius 상태가 변경되도록 했다.

이 방법으로 하기 전에 너무 복잡한 방식으로 해서 2시간을 날렸다.

진작 이 방법으로 할 걸

private func createSettingsMenu() -> UIMenu {
    let celsiusAction = UIAction(
        title: "섭씨",
        image: UIImage(systemName: "degreesign.celsius"),
        state: isCelsius ? .on : .off
    ) { [weak self] _ in
        self?.isCelsius = true
    }

    let fahrenheitAction = UIAction(
        title: "화씨",
        image: UIImage(systemName: "degreesign.fahrenheit"),
        state: isCelsius ? .off : .on
    ) { [weak self] _ in
        self?.isCelsius = false
    }

    return UIMenu(title: "온도 설정", children: [celsiusAction, fahrenheitAction])
}

그리고 단위 전환 시 UI 업데이트를 보장하기 위해 updateTemperatureUnit 메서드를 호출해줘야한다.

private func updateTemperatureUnit() {
    updateMenu() // 메뉴 상태 업데이트
    for cell in pageCollectionView.visibleCells {
        if let weatherCell = cell as? WeatherPageCell {
            weatherCell.weatherView.updateTemperatureUnit(isCelsius: isCelsius)
        }
    }
}

UI와 데이터 동기화 (WeatherView)

WeatherView는 온도 데이터를 표시하고 섭씨/화씨 전환 시 UI를 업데이트해준다.

public func updateTemperatureUnit(isCelsius: Bool) {
    let targetUnit: TempUnit = isCelsius ? .celsius : .fahrenheit

    if let currentTempText = temperatureLabel.text?.dropLast(),
       let currentTempValue = Double(currentTempText) {
        let convertedCurrent = SettingsManager.convertTemperature(value: currentTempValue, to: targetUnit)
        temperatureLabel.text = "\(Int(convertedCurrent))°"
    }
}

트러블슈팅

1. 데이터 손실 문제

  • 문제: 섭씨/화씨 변환 시 UI의 텍스트를 다시 읽어 변환한 결과 값이 축적되어 부정확한 결과 발생했다.
  • 해결: 원본 데이터를 유지하고 이걸 기반으로 변환했다.
private var originalTemperature: Double = 0.0

func setOriginalTemperature(_ temperature: Double) {
    originalTemperature = temperature
    updateTemperatureUnit(isCelsius: true)
}

2. 메뉴 상태와 UI 비동기 문제

  • 문제: 메뉴에서 단위를 선택해도 상태가 UI에 반영되지 않았다.
  • 해결: 메뉴 상태가 변경이 됐을 대 바로 updateMenuupdateTemperatureUnit 호출했다.
private var isCelsius: Bool = true {
    didSet {
        UserDefaults.standard.set(isCelsius, forKey: "isCelsius")
        updateTemperatureUnit()
    }
}

3. 앱 재실행 시 상태 초기화 문제

  • 문제: 앱을 재실행하면 이전에 선택한 단위가 유지되지 않고 바뀌었다.
  • 해결: UserDefaults에서 값을 불러와서 초기화를 진행했다.
private var isCelsius: Bool = UserDefaults.standard.object(forKey: "isCelsius") as? Bool ?? true

음...

이번 작업에서 원본 데이터 관리의 중요성을 좀 알게 됐다. UI에 표시된 값을 기반으로 로직을 처리하면 데이터 손실이 발생할 수 있다는 점과 UserDefaults를 통해 사용자 설정을 유지는 방법이라던지, 그리고 UIMenu를 활용하면서 사용자 경험을 개선하기 위해 인터페이스에 적절한 메뉴를 제공하는 방법같은 걸 공부할 수 잇었다.

profile
iOS 좋아. swift 좋아.

0개의 댓글

관련 채용 정보