iOS프로젝트/Funch(넥스터즈)

SwiftUI 화면 dismiss 상황에서 흰 화면 나타나는 문제

lgvv 2024. 9. 22. 17:22

SwiftUI 화면 dismiss 상황에서 흰 화면 나타나는 문제

 

SwiftUI 기반의 코드에서 화면 dismiss 상황에서 흰 화면이 나타나는 문제가 발생하여 그 과정을 기록

 

글의 순서

  • 해당 현상에 대한 영상
  • 프로젝트에서 사용한 화면 전환 방식
  • 해당 현상이 발생했을 때 흰화면이 나타나는 원인 분석
  • 어떻게 해결하는게 좋을까?
  • 현재 상황에서 해당 문제가 왜 발생할까?
  • 어떤 방식을 선택하는게 좋을까?
  • 향후 생각할 포인트.

 

 

해당 현상에 대한 영상

문제 현상 재현을 위해서 내부 컨텐츠를 제거하고 화면전환.

해당 현상 재현 플로우

  • 홈 > 멀티 프로필 > 프로필 생성 > 프로필 생성 닫기 > 멀티 프로필 닫기 > 홈
  • 홈 <-> 멀티 프로필 간에는 문제가 되는 코드로 작성
  • 멀티 프로필 <-> 프로필 생성 간에는 문제가 없는 코드로 작성

 

데모 영상



프로젝트에서 사용한 화면 전환 방식

 

HomeUI 모듈 내부에서 구현된 부분을 가리면서 HomeViewBuilder를 활용해 의존성을 주입하여 외부 상호작용 등을 구성

기존 코드에서 화면 전환 방식은 UI간의 순환참조 문제를 해결하고자 Coordinator 모듈을 두고, 해당 모듈을 구현하는 App모듈이 담당.

 

AppViewModel에서 화면전환에 대한 관심사를 분리하기 위해 HomePresentation을 별도로 두어 처리.

> 이 지점에서 여기서 문제점 발생

 

아래 사진 3장은 차례로

  • HomeViewBuilder 및 fullScreenCover 방식으로 화면전환하는 방식
  • ViewModel에 정의된 화면전환을 담당할 상태 선언 방식
  • Coordinator 모듈에 정의된 부분

 

의존성 주입 및 프레젠테이션 화면전환 방식
ViewModel에 정의된 CoordinatorAction

 

Coordinator 모듈에 정의된 화면전환 정의


해당 현상이 발생했을 때 흰화면이 나타나는 원인 분석

화면이 닫힐 때 EmptyView()가 호출 되어 하얀색 화면이 나타난 후 닫히는 것처럼 보임

 

위에 사진 두번째를 보면 ViewModel에서 화면전환의 초기값이 nil로 선언되어 있음.

  • 사유: 전환할 화면이 없으므로 당연히 nil로 설정되어야 함.

분리한 화면 코드에서 nil이 호출되는 모습

 


어떻게 해결하는게 좋을까?

 

우선 HomePresentationView가 꼭 View일 필요는 없음.

따라서 View를 제거하는 방식으로 시도

  • 1. HomePresentation에서 `: View` 제거
  • 2. 대신 body에 `@ViewBuilder`에 추가
  • 3. 사용하는 부분에서 명시적으로 `.body`를 호출하도록 수정

 

수정된 PresentationView

 

 

여기는 사용하는 영역

- 아래 코드에서 명시적으로 `body`를 호출해주고 있음.

문제를 수정한 코드

 

 

 

현재 상황에서 해당 문제가 왜 발생할까?

문제 원인은 HomPresentationView 영역에 body를 명시적으로 작성하는지 여부에 따라 따라 해당 현상이 발생하고 안하고 차이가 있었다.

 

body를 명시적으로 작성한 경우 기존 `: View`를 넣고 작성해봐도 문제가 없었음.

 

바디를 없애보자

 

바디를 명시하지 않을경우 View의 nil이 호출된다.

 

 

어떤 방식을 선택하는게 좋을까?

원인을 찾고나서 선택한 방식은 처음에 작성했던 대로 `@ViewBuilder`를 사용하는 방식으로 선택

  • 사유: `@ViewBuidler`를 작성할 경우 사용하는 쪽에서 `.body`를 반드시 작성하지 않으면 컴파일러가 오류를 발생시킴.

 

 

향후 생각할 포인트.

어떤게 문제인지 정확한 포인트를 찾지는 못함.

 

그래도 의심되는 부분 및 생각할 부분을 정리해보자면

  • 1. Presentation에서 `@ObservedObject`을 사용하여 외부에서 관찰하는 부분에서 문제가 있음.
    • 대안 1: @EnvironmentObject로 변경
      • 결정: 교체하지 않음.
      • 사유: 전역적으로 쓰여서 처음에 DIContainer를 만들때 전역적으로 사용하게 만든것과 동일해지며, App에 의존되는 코드를 외부에서 쓰면 사실상 전역적으로 관리되는 접근 가능한 코드
    • 대안 2: WWDC 24에서 발표한 ContainerValues 활용
      • 결정: 미적용
      • 사유: 현재 기준으로 적용하기엔 타겟이 높음.
  • 2. body를 명시적으로 작성하는 것과 작성하지 않는 부분에 따른 SwiftUI View의 생명주기 차이.