2024.09.24 작성
OS : macOs
개발환경 : Android Studio, Xcode
개발언어 : Dart
프레임워크 : Flutter
앱 업데이트 직전에 발견한 오류...😓
불 던지기 기능을 사용할 때, 텍스트를 포함해서 불을 던지면 오류가 났다.
애뮬레이터에서는 이런 오류가 안 떴는데, 테스트플라이트에서만 발생한 오류이다.
이번에 내가 새로 추가한 기능인데... 뭔가 꼬인 듯?
어쨌든, Xcode에서 실제 아이폰을 연결해서 실행하면 실시간으로 로그를 확인할 수가 있다. 그래서 이걸 통해 오류 로그를 잡았다.
오류 로그는 다음과 같다.
[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: Null check operator used on a null value
#0 StatefulElement.state (package:flutter/src/widgets/framework.dart:5205)
#1 Element.findAncestorStateOfType (package:flutter/src/widgets/framework.dart:4435)
#2 Navigator.of (package:flutter/src/widgets/navigator.dart:2631)
#3 MissionFireState.completeThrowFireModal.<anonymous closure>.<anonymous closure> (package:moing_flutter/mission_fire/mission_fire_state.dart:269)
#4 new Future.delayed.<anonymous closure> (dart:async/future.dart:427)
#5 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18)
#6 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398)
#7 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429)
#8 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:189)
Future.delayed가 실행될 때 Navigator.pop()을 호출하는 dialogContext가 이미 null이 되어있기 때문에 발생하는 것이었다.
사진과 같이 해당 부분 코드를 바꿔주니 잘 되었다.
builder: (BuildContext dialogContext) {
Future.delayed(const Duration(seconds: 2), () {
if (ModalRoute.of(dialogContext)?.isCurrent ?? false) {
Navigator.of(dialogContext).pop();
}
});
비동기 작업 중에 모달이 닫히는 시점을 ModalRoute.of(dialogContext)?.isCurrent를 사용해 안전하게 처리하여, 모달만 닫히고 메인 화면은 유지되도록 수정했다.
모달이 열려 있는 상태에서 Navigator.pop()이 잘못된 context에 호출되지 않도록 하였다.
Flutter는 비동기 프로그래밍을 자주 사용한다.
그래서 네트워크 요청이나 타이머를 사용한 작업은 일정 시간이 지나면 완료되는데, 그 사이에 위젯의 상태가 변경되거나 사라질 수 있다.
이때 비동기 작업이 완료되었을 때 null 상태가 된 객체에 접근하면 Null check operator used on a null value 같은 오류가 발생하기에, 항상 상태를 확인하고 null 처리를 하는 것이 필수적이다.
결론적으로 null 체크와 상태 확인이 Flutter에서 중요하다.
앱이 예기치 않게 중단되지 않고 사용자 경험을 저해하지 않도록 null 체크를 잘 해줘야 한다.