무지성 MainActor를 붙인 상황에서 데이터가 로드되기 전에 뷰가 그려지는 문제 해결

2024. 12. 2. 18:43·UIKit

안녕하세요! 집주인의 얼굴천재 박효준입니다!

MainActor를 여기저기 쓰다가 보니 문제가 발생한 부분을 공유드리고자합니다!

가봅시다~~ ᕦ(ò_óˇ)ᕤ

문제 상황

input.sink { [weak self] event in
    switch event {
    case .viewDidLoad:
        do {
            self?.fetchMemorialHouse()
            try self?.fetchCategory()
            self?.output.send(.fetchedMemorialHouseAndCategory)
        } catch {
            self?.output.send(.fetchedFailure("데이터 로드 중 에러가 발생했습니다."))
            MHLogger.error("에러 발생: \\(error.localizedDescription)")
				...
	      }
	  }.store(in: &cancellables)
}

현재 HomeViewController가 HomeViewModel의 houseName을 참조하고 있다가

fetchMemorialHouseUseCase.execute()가 끝나면 houseName을 업데이트해주고 그때 뷰를 그리는 방식이다.

그런데, UseCase가 잘 동작하고 프로퍼티가 업데이트가 되었는데 왜 화면은 초기값 “” 빈 문자열이 들어갈까 ?

이를 해결해나간 과정을 말해보겠다.


문제 해결

먼저 MainActor로 덕지덕지 붙어있는 코드가 문제라 생각했다.

메소드 자체도 MainActor이고, 내부 Task에서 또 MainActor라고 선언해두었다.

첫 번째로 위 사진 69번째 Task 우측에 있는 @MainActor를 제거해봤는데 결과는 여전했다.

디버깅을 여러 차례 시도한 결과 useCase 동작이 끝나기 전에 self?.output.send(.fetchedMemorialHouseAndCategory) 을 하는 것 같았다.

그래서 함수 자체를 async하게 만들고 Input을 보내는 것도 await에 의해 끝났을 때 처리하는 것으로 바꿔주었다.

private func fetchMemorialHouse() async throws {
    let memorialHouse = try await fetchMemorialHouseUseCase.execute()
    self.houseName = memorialHouse.name
    self.bookCovers = memorialHouse.bookCovers
    self.currentBookCovers = memorialHouse.bookCovers
}

private func fetchCategory() async throws {
    let categories = try await fetchCategoryUseCase.execute()
    self.categories += categories
}

위와 같이 함수는 그냥 async로 동작하게 하고,

이를 호출하는 곳에서 하나의 Task로 묶고 거기서 await 되면 input.send를 하게 하였다.

input.sink { [weak self] event in
    switch event {
    case .viewDidLoad:
        Task {
            do {
                try await self?.fetchMemorialHouse()
                try await self?.fetchCategory()
                self?.output.send(.fetchedMemorialHouseAndCategory)
            } catch {
                self?.output.send(.fetchedFailure("데이터 로드 중 에러가 발생했습니다."))
                MHLogger.error("에러 발생: \\(error.localizedDescription)")
            }
        }
    case .selectedCategory(let index):
        self?.filterBooks(with: index)
    }
}.store(in: &cancellables)

완벼쿠 하네요 ~

무지성 MainActor는 좋지 않다는 것을 알았습니다.

'UIKit' 카테고리의 다른 글

NotificationCenter의 removeObserver를 해야할까?  (0) 2024.12.03
뷰 그리는 방식에 대한 논의(Factory vs MH커스텀 vs VC에서 설정)  (0) 2024.12.02
CollectionViewCell들 간의 Drag & Drop 구현하기  (1) 2024.12.01
CALayer를 사용할 때 발생하는 메모리 크래시  (0) 2024.11.29
런타임 시점에 Constraint를 조절하여 애니메이션 구현하기  (1) 2024.11.19
'UIKit' 카테고리의 다른 글
  • NotificationCenter의 removeObserver를 해야할까?
  • 뷰 그리는 방식에 대한 논의(Factory vs MH커스텀 vs VC에서 설정)
  • CollectionViewCell들 간의 Drag & Drop 구현하기
  • CALayer를 사용할 때 발생하는 메모리 크래시
집주인들의 기술 블로그
집주인들의 기술 블로그
Memorial-House 집주인들의 기술 블로그
  • 집주인들의 기술 블로그
    Memorial House
    집주인들의 기술 블로그
  • 전체
    오늘
    어제
    • 🏠 집주인들 글 모아보기 (30)
      • iOS (5)
      • Combine (0)
      • Swift (7)
      • UIKit (7)
      • Xcode (6)
      • Architecture, Design Patter.. (3)
      • 기획 (1)
      • Github actions (1)
  • 링크

    • Github-Repository
    • Github-Wiki
    • Notion
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
집주인들의 기술 블로그
무지성 MainActor를 붙인 상황에서 데이터가 로드되기 전에 뷰가 그려지는 문제 해결
상단으로

티스토리툴바