Расположение флаттера не работает при горячей перезагрузке в Xcode

#ios #flutter #location #maps

Вопрос:

На моей домашней странице я показываю полноэкранную карту с маркерами, загруженными из базы данных Firestore.

Я использую будущий конструктор для получения некоторых настроек и текущего положения пользователя. Маркеры отображаются в зависимости от расстояния между текущим положением и положением маркера.

Все работает нормально при первом запуске приложения (я использую эмулятор Xcode), но каждый раз при перестроении страницы (например, с горячей перезагрузкой) будущий конструктор застревает, пытаясь получить текущее местоположение, что не работает.

 import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:location/location.dart';
import 'package:map_app/providers/settings_provider.dart';
import 'package:map_app/widget/my_drawer.dart';
import 'package:platform_maps_flutter/platform_maps_flutter.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:intl/intl.dart';

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Location _location = Location();
  late LocationData
      _currentPosition; // posizione corrente che verrà calcolata nell'init

  bool showProgress = false;

  CollectionReference segnalazioni =
      FirebaseFirestore.instance.collection('segnalazioni');

  Future<LocationData> getCurrentLocation() async {
    LocationData currPos; // = await _location.getLocation();

    PermissionStatus _permissionGranted;
    bool _serviceEnabled;

    _serviceEnabled = await _location.serviceEnabled();
    if (!_serviceEnabled) {
      _serviceEnabled = await _location.requestService();
      if (!_serviceEnabled) {
        return Future.error('I servizi di localizzazione non sono abilitati');
      }
    }

    _permissionGranted = await _location.hasPermission();
    if (_permissionGranted == PermissionStatus.denied) {
      _permissionGranted = await _location.requestPermission();
      if (_permissionGranted != PermissionStatus.granted) {
        return Future.error(
            'I permessi di accesso alla posizione non sono abilitati');
      }
    }

    // ora recupero la posizione corrente
    currPos = await _location.getLocation().timeout(
      const Duration(seconds: 5),
      onTimeout: () {
        print('timeout');
        return Future.error('Timeout durante accesso alla posizione');
      },
    );

    currPos = await _location.getLocation();
    print('curr location : ${currPos.toString()}');

    return currPos;
  }

  // future utilizzato per caricare le impostazionie
  Future<int> loadSettings() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();

    final dist = prefs.getInt('distanza') ?? 1;

    return dist;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      drawer: MyDrawer(),

      body: FutureBuilder(

          future: Future.wait([
            loadSettings(),
            getCurrentLocation(),
            //... More futures
          ]),
          builder: (
            context,
            // List of dynamic(results of all futures above)
            AsyncSnapshot<List<dynamic>> snapshotMultiplo,
          ) {
            // così verifico che TUTTI i future che sto aspettando siano a posto
            if (!snapshotMultiplo.hasData) {
              return Center(child: CircularProgressIndicator());
            }

            if (snapshotMultiplo.connectionState == ConnectionState.waiting) {
              return Center(child: CircularProgressIndicator());
            }

            return StreamBuilder<QuerySnapshot>(
                stream: segnalazioni.snapshots(),
                builder: (BuildContext context,
                    AsyncSnapshot<QuerySnapshot> markerSnapshot) {
                  if (!markerSnapshot.hasData) {
                    return LinearProgressIndicator(); //CircularProgressIndicator();
                  }

                  if (markerSnapshot.connectionState ==
                      ConnectionState.waiting) {
                    return LinearProgressIndicator(); //CircularProgressIndicator();
                  }

                  //print('distanza da settings : ${distanzaSnapshot.data}');

                  return Consumer<SettingsProvider>(
                      builder: (context, settings, child) {
                    return PlatformMap(
                      myLocationButtonEnabled: true,
                      myLocationEnabled: true,
                      mapType: MapType.normal,
                      initialCameraPosition: CameraPosition(
                          target: LatLng(
                            snapshotMultiplo.data![1].latitude,
                            snapshotMultiplo.data![1].longitude,
                          ),
                          zoom: 10),
                      markers: markerSnapshot.data!.docs.map(
                        (document) {
                          print(document.toString());
                          int distanza = Geolocator.distanceBetween(
                            // _currentPosition.latitude!,
                            //_currentPosition.longitude!,
                            snapshotMultiplo.data![1].latitude,
                            snapshotMultiplo.data![1].longitude,
                            document['posizione'].latitude,
                            document['posizione'].longitude,
                          ).round();

                          return Marker(
                            markerId: MarkerId(document.id),
                            position: LatLng(
                              double.parse('${document['posizione'].latitude}'),
                              double.parse(
                                  '${document['posizione'].longitude}'),
                            ),
                            
                            visible: distanza < settings.diamRicerca * 1000
                                ? true
                                : false,
                            infoWindow: InfoWindow(
                              title: DateFormat('dd-MM-yyyy')
                                  .format(document['data'].toDate())
                                  .toString(),
                              snippet:
                                  '${document['descrizione']} , distanza = ${Geolocator.distanceBetween(                                                                     snapshotMultiplo.data![1].latitude,
                                snapshotMultiplo.data![1].longitude,
                                document['posizione'].latitude,
                                document['posizione'].longitude,
                              ).round()}',
                            ),
                          );
                        },
                      ).toSet(),
                      onTap: (location) => print('onTap: $location'),                                                    
                    );
                  });
                });
          }),
    );
  }
}
 

Я использую конструктор будущего только для получения настроек, текущей позиции и загрузки страницы, а конструктор потоков-для загрузки новых маркеров при их добавлении в Firestore.

На Android все в порядке, поэтому я не совсем понимаю, почему на iOS исследование местоположения работает только в первый раз.

Есть идеи, почему?