ReleaseAppUntilDie / GatheRunner

GatherRunner
2 stars 0 forks source link

[해결] GatherRunner 앱에서 '활동'뷰로의 전환이 2번이상 진행되는 경우 에러 발생하며 앱 종료되는 증상 발생 #71

Closed wh5929 closed 1 year ago

wh5929 commented 2 years ago

에러 검토 요청

제목과 같이 다른 뷰에서 활동 뷰로 2번 이상 전환 하게 되는 경우 GatherRunner.swift 의 @main 진입점에서 Fatal Error: Out of Index 에러 발생하며 앱 종료되는 증상 확인

image
wh5929 commented 2 years ago

에러 포인트와 임시 해결방법

SelecedTab.swift 파일에 선언된 Singleton 패턴 또는 @EnvironmentObject / @StateObject / @ObservedObject 를 사용하여 서로 다른 뷰에서 프로퍼티를 공유할 경우 해당 문제가 발생하는것으로 확인됨. 원인은 파악하지 못함.

임시 해결방법 -> MainTabView 자체가 항상 실행되어 있는 인스턴스이고 @State 를 사용하여 tabIndex 값을 저장한다고 했을때 정상적으로 tabView 사용이 가능.(현 구성에서 tabIndex 정보를 담은 프로퍼티를 다른 뷰와 공유할 필요가 없음)

SwiftUI 사용지침에서 @State / @Binding 은 여러 뷰에서 사용하지 않도록 안내하고 있지만, 현재 구성으로는 @Binding 을 EmptyActivityView 에서만 사용하여 MainTabView 로 부터 index 정보를 받아오면 되는 상황이기 때문에 문제될것은 없어보인다.

다른 해결방법을 찾지 못하는 경우 대안이 될 수 있습니다.

DalioKim commented 2 years ago

다른뷰에서 활동뷰로 2번이상 전환한다는말이 무슨말인가요?

다른 뷰 -> 활동 뷰 -> 다른 뷰 -> 활동 뷰의 상황을 말씀하시는건가요?

DalioKim commented 2 years ago

(현 구성에서 tabIndex 정보를 담은 프로퍼티를 다른 뷰와 공유할 필요가 없음)

공유할 필요가 없지 않습니다. 환경변수를 통해 탭뷰의 인덱스를 공유해야, 다른 뷰에서도 화면으로 이동할 수 있습니다. https://seons-dev.tistory.com/m/entry/SwiftUI-EnvironmentObject%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EB%B7%B0%EA%B0%84%EC%97%90-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B3%B5%EC%9C%A0

SwiftUI 사용지침에서 @State / @binding 은 여러 뷰에서 사용하지 않도록 안내하고 있지만, 현재 구성으로는 @binding 을 EmptyActivityView 에서만 사용하여 MainTabView 로 부터 index 정보를 받아오면 되는 상황이기 때문에 문제될것은 없어보인다.

EmptyActivityView에서 MainTabView 로 부터 index를 받아온다는건 의존성 문제가 생깁니다. 이 두 뷰간에는 의존성이 있어야할 이유가 없어보입니다.

wh5929 commented 2 years ago

다른뷰에서 활동뷰로 2번이상 전환한다는말이 무슨말인가요?

다른 뷰 -> 활동 뷰 -> 다른 뷰 -> 활동 뷰의 상황을 말씀하시는건가요?

네. 아래 이미지와 같이 활동뷰에 두번째 진입시에 앱 종료됩니다. Simulator Screen Recording - iPhone 14 - 2022-10-19 at 13 15 22

DalioKim commented 2 years ago

우선 좀 더 확인해야하되지만, EmptyActivityView를 확인해보니까 사용이 잘못되었네요. 환경변수는 싱글턴이지지만 environmentObject 연산자를 통해서 공유되어야 합니다.

매번 이 작업을 하기에 번거로울까봐,

.buttonStyle(TabBarButton(TabItem.MainComponent.run.tag)) 를 통해 정의해뒀는데


EmptyActivityView
            Button {
                SelectedTab.shared.index = TabItem.MainComponent.run.tag
            } label: {

environmentObject로 공유되지 않은 상태로 바로 접근하게 되어있네요.

DalioKim commented 2 years ago

그리고 다른 이야기인데 EmptyActivityView 네이밍이 기록이 없을때 보여주는 화면인데 마치 그냥 빈 화면이라는 느낌을 주네요.

wh5929 commented 2 years ago

(현 구성에서 tabIndex 정보를 담은 프로퍼티를 다른 뷰와 공유할 필요가 없음)

공유할 필요가 없지 않습니다. 환경변수를 통해 탭뷰의 인덱스를 공유해야, 다른 뷰에서도 화면으로 이동할 수 있습니다. https://seons-dev.tistory.com/m/entry/SwiftUI-EnvironmentObject%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EB%B7%B0%EA%B0%84%EC%97%90-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B3%B5%EC%9C%A0

답변

tabIndex 는 MainTabView 에서 계속 갖고 있으니 MainTabView 의 tab bar 를 이용해 뷰 전환을 진행할 경우 다른 뷰와 공유할 필요가 없습니다. 그러나 EmptyActivityView 와 같이 다른 뷰로 이동하는 버튼등을 통해 뷰 전환을 할때는 프로퍼티를 공유해야 하구요. 에러의 원인을 찾는다면 현 구성을 유지해도 되겠죠.

SwiftUI 사용지침에서 @State / @binding 은 여러 뷰에서 사용하지 않도록 안내하고 있지만, 현재 구성으로는 @binding 을 EmptyActivityView 에서만 사용하여 MainTabView 로 부터 index 정보를 받아오면 되는 상황이기 때문에 문제될것은 없어보인다.

EmptyActivityView에서 MainTabView 로 부터 index를 받아온다는건 의존성 문제가 생깁니다. 이 두 뷰간에는 의존성이 있어야할 이유가 없어보입니다.

wh5929 commented 2 years ago

그리고 다른 이야기인데 EmptyActivityView 네이밍이 기록이 없을때 보여주는 화면인데 마치 그냥 빈 화면이라는 느낌을 주네요.

그렇네요. 그리고 러닝 기록이 없을때 EmptyActivityView 가 실행되게끔 하는 분기점이 아직 없더라구요.

wh5929 commented 2 years ago

우선 좀 더 확인해야하되지만, EmptyActivityView를 확인해보니까 사용이 잘못되었네요. 환경변수는 싱글턴이지지만 environmentObject 연산자를 통해서 공유되어야 합니다.

매번 이 작업을 하기에 번거로울까봐,

.buttonStyle(TabBarButton(TabItem.MainComponent.run.tag)) 를 통해 정의해뒀는데


EmptyActivityView
            Button {
                SelectedTab.shared.index = TabItem.MainComponent.run.tag
            } label: {

environmentObject로 공유되지 않은 상태로 바로 접근하게 되어있네요.

그렇네요. 그런데 EmptyActivityView는 현재 화면이 실행되지 않는 상태라 해당 문제와는 연관이 없는듯합니다.

DalioKim commented 2 years ago

tabIndex 는 MainTabView 에서 계속 갖고 있으니 MainTabView 의 tab bar 를 이용해 뷰 전환을 진행할 경우 다른 뷰와 공유할 필요가 없습니다. 그러나 EmptyActivityView 와 같이 다른 뷰로 이동하는 버튼등을 통해 뷰 전환을 할때는 프로퍼티를 공유해야 하구요. 에러의 원인을 찾는다면 현 구성을 유지해도 되겠죠.

의존성이라는 것에 대해 이해도가 필요하실 것 같습니다. MainTabView의 tabIndex 프로퍼티를 다른 뷰에서 구현할때 사용한다는건, MainTabView의 tabIndex가 수정될때마다 다른 뷰들도 수정되어야 한다는 뜻입니다.

이런걸 의존성이라고하는데 코드의 구조상 MainTabView와 다른 뷰들이 이러한 의존관계를 가질 필요도 가져서도 안됩니다.

이 의존성을 없애기 위해서 SelectedTab라는 환경변수를 사용하는거고요.

의존성 설명

DalioKim commented 2 years ago

저 화면이랑 똑같이 했는데 에러발생안하는데

화면에서 탭뷰로만 이동하신거 맞나요?

wh5929 commented 2 years ago

현재 checkout 중인 commit 부분이 아래의 빈 활동(EmptyActivityView) 창이 보이시나요?

image

그렇다면 최근 재승님이 개발한 graphview 가 반영된 develop 브랜치 checkout 후에 확인해주시면 될듯합니다.

DalioKim commented 2 years ago

현재 checkout 중인 commit 부분이 아래의 빈 활동(EmptyActivityView) 창이 보이시나요? image

그렇다면 최근 재승님이 개발한 graphview 가 반영된 develop 브랜치 checkout 후에 확인해주시면 될듯합니다.

현재 develop 기준으로 테스트한거에요. feature/activitylistview 말씀하시는건가요?

wh5929 commented 2 years ago

에러 내용 정리

xcode 14 - 시뮬레이터 ios 16 버전에서 ForEach 사용시 발생하는 문제인것으로 확인

@main 진입점 Fatal Error: Index out of range 에 관한 stackoverflow 페이지 참고

에러 포인트는 GraphBottomSheetView - PickerView - Choose period 피커부분의 ForEach에서 문제 발생. 나머지 ForEach 에서는 문제 발생하지 않음.

문제가 되는 부분의 ForEach 부분을 주석처리 했을때 정상 작동확인. 정확히는 Text($0) 에서 에러 발생. 아래 사진 참조. image

iPadOS 15.7 에서 발생한 에러

IMG_3084

해당 부분의 문제 확인중.

wh5929 commented 1 year ago

Xcode 14.1 마이너 업그레이드 후 해당 증상 사라짐 -> 이슈 종료