1 분 소요

날씨 앱 뷰에 데이터가 갱신되지 않는 문제해결

날씨 앱이 날씨 데이터를 받아오고 뷰에 보여야 하는데 보였다가 안 보였다가 할 때가 있습니다. 😱 어디가 문제인지 브레이크포인트를 걸면서 찾아보았습니다.

의심이 가는 부분은 뷰 생성 시점과 뷰 바인딩 시점 그리고 데이터 수신 시점이 있는데 여기서 무언가 순서가 잘못되었나 싶었습니다. 🤔

먼저 뷰모델을 생성하는 시점입니다. 뷰모델은 뷰 컨트롤러를 초기화할 때 생성하게 되어있습니다. 그리고 viewDidLoad() 단계에서 뷰를 바인딩합니다.

final class WeatherViewController: UIViewController {
    // 뷰모델 생성
    private var weatherViewModel = WeatherViewModel()
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 데이터 바인딩
        bindingViews()
    }
    ...
}

뷰모델에서는 초기화할 때 데이터를 요청합니다.

final class WeatherViewModel {
    ...
    init() {
        // 현재 날씨 데이터 요청
        fetchCurrentWeatherData()
        // 시간별 예보 날씨 데이터 요청
        fetchForecastWeatherData()
    }
    ...
}

위 코드를 보면 뷰모델이 초기화하는 과정에서 데이터를 요청합니다. 그리고 바인딩은 viewDidLoad() 단계에서 수행합니다. 그러면 메서드 호출 순서가 다음과 같이 됩니다.

뷰모델 생성 -> 날씨 데이터 요청 -> 뷰 생성 -> 뷰 바인딩 순으로 호출됩니다.

분석하면서 뭔가 호출 순서가 잘못되었다고 느꼈습니다. 뷰를 생성하거나 바인딩을 하지 않았는데 데이터를 요청하고 있습니다. 만약에 날씨 데이터가 뷰 생성과 뷰 바인딩이 이뤄지기 이전에 도착하면 뷰를 갱신할 수 없게 됩니다. 따라서 메서드 호출 순서는 다음과 같이 변경되어야 합니다.

뷰모델, 뷰 생성 -> 뷰 바인딩 -> 날씨 데이터 요청 순으로 호출하면 뷰가 생성되고 바인딩 되었다는 것이 보장되기 때문에 뷰가 제대로 갱신되리라 생각합니다.

앱을 실행하자마자 데이터를 요청하고 뷰에 반영해야 하므로 데이터 요청 시점을 viewDidLoad()에서 뷰 바인딩 이후에 호출하도록 개선해볼 수 있습니다.

뷰모델에서는 초기화 과정에서 데이터를 요청하는 구문을 제거하고 별도의 데이터 요청 메서드 loadWeatherData() 를 만들었습니다. 이 메서드는 뷰 컨트롤러에서 뷰 바인딩 이후에 호출하도록 합니다.

final class WeatherViewModel {
    ...
    func loadWeatherData() {
        fetchCurrentWeatherData()
        fetchForecastWeatherData()
    }
    ...
}

뷰 컨트롤러에서는 메서드 호출 순서를 변경하였습니다. (뷰모델에서 새로 작성한 메서드 호출)

final class WeatherViewController: UIViewController {
    // 뷰모델 생성
    private var weatherViewModel = WeatherViewModel()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // 뷰 바인딩
        bindingViews()
        // 날씨 데이터 요청
        weatherViewModel.loadWeatherData()
    }
    ...
}

위와 같이 변경하니까 더는 뷰가 안 보이는 경우가 발생하지 않았습니다. 같은 문제가 발생하지 않도록 앞으로도 생성 순서, 초기화, 메서드 호출 순서를 잘 고려하여 작성할 수 있도록 노력해야겠습니다. 😎

댓글남기기