기본적으로 UI는 메인스레드에서 업데이트해야한다.
하지만 SwiftUI에서 EnvironmentObject등을 사용할 때 해당 변수값을 서버에서 받은 값으로 백그라운드에서 변경하게 된다면 UI를 백그라운드에서 업데이트하게되는 경우가 발생한다.
이런 경우 해당 값을 바꾸게 되는 백그라운드스레드의 메소드 위에 @MainActor
을 추가하면 된다.
그렇게되면 백그라운드 스레드에서 작업을 마친 후 돌아와 다음 코드를 실행할 때 항상 메인 스레드로 돌아와 실행하게 된다.
또한 비동기 방식으로 여러 값을 받아올 때에는 받아오는 변수 앞에 async를 붙여주면 된다.
이후 해당 변수를 사용하는 곳에서 변수 앞에 try await을 붙여준다.
@MainActor
func fetchWeather(location: CLLocation) async {
do {
async let fetchedCurrentWeather: CodableCurrentWeather = fetch(type: .weather, location: location)
async let fetchedForecast: CodableForecast = fetch(type: .forecast, location: location)
currentWeather = CurrentWeather(data: try await fetchedCurrentWeather)
forecastList = try await fetchedForecast.list.compactMap {
Forecast(data: $0)
}
} catch {
lastError = "Api 요청 실패"
}
}