I've written a Flutter App that use the Bloc Pattern and the GetIt package. It's really weird that the app works fine on Android device but on an iOS Simulator, it only shows a black screen...
Here my code:
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
AppInitializer.init();
runApp(App());
}
app_initializer.dart
import 'package:authentication_repository/authentication_repository.dart';
import 'package:get_it/get_it.dart';
import 'package:techniciens/blocs/blocs.dart';
import 'package:user_repository/user_repository.dart';
class AppInitializer {
static final getIt = GetIt.instance;
static void init() {
_registerSingletons();
_registerBlocSingletons();
}
static void _registerSingletons() {
getIt.registerSingleton(AuthenticationRepository()..user.first);
getIt.registerLazySingleton<UserRepository>(() => UserRepository());
}
static void _registerBlocSingletons() {
getIt.registerLazySingleton<AuthenticationBloc>(() => AuthenticationBloc(
authenticationRepository:
GetIt.instance.get<AuthenticationRepository>()));
getIt.registerLazySingleton<SettingsFormCubit>(() => SettingsFormCubit());
getIt.registerLazySingleton<UserInfoCubit>(() => UserInfoCubit());
}
}
app.dart
import 'package:authentication_repository/authentication_repository.dart';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:overlay_support/overlay_support.dart';
import 'package:techniciens/blocs/blocs.dart';
import 'package:techniciens/core/constants/constants.dart';
import 'package:techniciens/screens/screens.dart';
import 'package:get_it/get_it.dart';
import 'package:user_repository/user_repository.dart';
import 'core/theme/app_theme.dart';
class App extends StatelessWidget {
final AuthenticationRepository _authenticationRepository =
GetIt.instance.get<AuthenticationRepository>();
final UserRepository _userRepository = GetIt.instance.get<UserRepository>();
final AuthenticationBloc _authenticationBloc =
GetIt.instance.get<AuthenticationBloc>();
App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MultiRepositoryProvider(
providers: [
RepositoryProvider.value(value: _authenticationRepository),
RepositoryProvider.value(value: _userRepository),
],
child: BlocProvider<AuthenticationBloc>.value(
value: _authenticationBloc,
child: const AppView(),
),
);
}
}
class AppView extends StatefulWidget {
const AppView({Key? key}) : super(key: key);
@override
State<AppView> createState() => _AppViewState();
}
class _AppViewState extends State<AppView> {
final _navigatorKey = GlobalKey<NavigatorState>();
NavigatorState get _navigator => _navigatorKey.currentState!;
@override
Widget build(BuildContext context) {
return DynamicColorBuilder(
builder: (ColorScheme? lightColorScheme, ColorScheme? darkColorScheme) {
return OverlaySupport.global(
child: MaterialApp(
title: kLoginAppbarTitle,
theme: AppTheme.lightTheme(lightColorScheme),
darkTheme: AppTheme.darkTheme(darkColorScheme),
themeMode: ThemeMode.system,
debugShowCheckedModeBanner: false,
navigatorKey: _navigatorKey,
builder: (context, child) {
return BlocListener<AuthenticationBloc, AuthenticationState>(
listener: (_, state) {
switch (state.authStatus) {
case AuthenticationStatus.unauthenticated:
_navigator.pushAndRemoveUntil<void>(
LoginPage.route(), (route) => false);
break;
case AuthenticationStatus.authenticated:
_navigator.pushAndRemoveUntil<void>(
HomePage.route(), (route) => false);
break;
default:
break;
}
},
child: child,
);
},
onGenerateRoute: (_) => SplashPage.route(),
),
);
},
);
}
}
splash_page.dart
import 'package:flutter/material.dart';
class SplashPage extends StatelessWidget {
static Route<void> route() {
return MaterialPageRoute<void>(builder: (_) => const SplashPage());
}
const SplashPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator.adaptive(strokeWidth: 5),
),
);
}
}
As I could see in the Flutter Inspector and with some print
commands, the apps runs normally until the BlocListener
and falls on the onGenerateRoute
.
It gives me this
Launching lib/main.dart on iPhone 14 Pro in debug mode...
Running Xcode build...
Xcode build done. 13,8s
GrMtlCommandBuffer: WARNING: Creating MTLCommandBuffer while in background.
GrMtlCommandBuffer: WARNING: Creating MTLCommandBuffer while in background.
Debug service listening on ws://127.0.0.1:52638/_tIC8TChUyE=/ws
Syncing files to device iPhone 14 Pro...
flutter: dynamic_color: Dynamic color not detected on this device.
I've erased all data on the iOS Simulator, it doesn't give anything...
On Android Simulator, the code works super fine, but here, it fails every time on the Splash Screen.
Thank you for your help!
Enter the Info.plist. Most likely you have added a tag for your application to support multiple scenes (ie multiple windows or screens). It should look like this:
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIScene Settings</key>
<dict/>
</dict>
If you find it like this, remove the key that allows multiple windows. UISceneConfigurationsUIApplicationSceneManifest
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UIScene Settings</key>
<dict/>
</dict>
this is enough (and you can avoid a weird black screen!)