Возникло исключение при выполнении блока пользовательского интерфейса: неверный регион - PullRequest
1 голос
/ 27 июня 2019

Я пытаюсь получить местоположение пользователя в своем приложении React Native и переместить мой MapView в это местоположение. Когда приложение загружается, оно показывает местоположение (по умолчанию, а не из-за моего действия), но когда действие выполняется, я получаю эту ошибку:

Exception thrown while executing UI block: 
Invalid Region <center:+37.33233141, -122.03121860 span: +0.00044916, -0.05737702>

Объект региона, передаваемый моему MapView (из действий с моим местоположением), равен

{
  latitude: 37.33233141,
  longitude: -122.0312186,
  accuracy: 0.05,
  latitudeDelta: 0.0004491555874955085,
  longitudeDelta: -0.05737702242408729
};

Я на самом деле скопировал код из старого проекта, у которого была такая же проблема, а затем в какой-то момент перестал иметь проблему.

В любом случае, вот мой код:

MapScreen.js

import React, { Component } from "react";
import MapView, { Marker, Callout } from "react-native-maps";
import { connect } from "react-redux";

import { View, Button, Text, Platform, TextInput } from "react-native";

const CurrentRegionMarker = ({ currentRegion }) => {
  return currentRegion && currentRegion.showMarker ? (
    <Marker coordinate={currentRegion} pinColor={"green"} />
  ) : null;
};

class MapScreen extends Component {

  state = { region: null };

  render() {
    return (
      <View style={styles.container}>   
        <MapView
          style={{ flex: 1 }}
          showsUserLocation={true}
          region={this.props.currentRegion}
        >          
          <CurrentRegionMarker currentRegion={this.props.currentRegion} />
        </MapView>
      </View>
    );
  }
}

export default connect(({ location }) => ({
  currentRegion: location.currentRegion
}))(MapScreen);

locationActions.js

// @flow
import * as Location from "expo-location";
import * as Permissions from "expo-permissions";
import type {
  Location as LocationType,
  LocationAction
} from "../reducers/locationReducer";
import type { Saga } from "redux-saga";
import { call, put, select, takeEvery, all } from "redux-saga/effects";

export function getLocationAsync(): LocationAction {
  return { type: "USER_LOCATION_START" };
}

export function* getLocationSaga(): Saga<void> {
  try {
    const region = yield call(getUserLocation);
    yield put({ type: "USER_LOCATION_SUCCESS", region });
  } catch (error) {
    yield put({ type: "USER_LOCATION_FAILURE", error: error.message });
  }
}

async function getUserLocation(): LocationType {
  let { status } = await Permissions.askAsync(Permissions.LOCATION);
  if (status !== "granted") {
    return console.warn("Permission to access location was denied");
  }
  let location = await Location.getCurrentPositionAsync({});
  let { latitude, longitude } = location.coords;
  let accuracy = 0.05;
  let region = { latitude, longitude, accuracy };
  console.log("direct", calculateRegion(region));

  console.log("interpolated", { ...region, ...calculateRegion(region) });
  return { ...calculateRegion(region), accuracy };
}

function calculateRegion({
  latitude,
  longitude,
  accuracy = 0.05
}): LocationType {
  const oneDegreeOfLongitudeInMeters = 111.32;
  const circumference = 40075 / 360;
  const latitudeDelta = accuracy / oneDegreeOfLongitudeInMeters;
  const longitudeDelta = accuracy * (1 / Math.cos(latitude * circumference));
  const region = { latitude, longitude, latitudeDelta, longitudeDelta };
  return region;
}

export default function* locationSaga(): Saga<void> {
  yield all([yield takeEvery("USER_LOCATION_START", getLocationSaga)]);
}

locationReducer.js

// @flow

const initialState: LocationState = {
  currentRegion: {
    latitude: 0,
    longitude: 0,
    latitudeDelta: 0.00922,
    longitudeDelta: 0.00421,
    showMarker: false
  }
};

export default function dealsReducer(
  state: LocationState = initialState,
  action: LocationAction
): LocationState {
  switch (action.type) {
    case "USER_LOCATION_SUCCESS":
      return { ...state, currentRegion: action.region };
    case "USER_LOCATION_FAILURE":
      return { ...state, error: action.error };
    default:
      return state;
  }
}

export type Location = {
  latitude: number,
  longitude: number,
  latitudeDelta: number,
  longitudeDelta: number,
  showMarker?: boolean
};
type LocationState = {
  +currentRegion: Location,
  +error: ?string
};

export type LocationAction =
  | { type: "USER_LOCATION_START" }
  | {
      type: "USER_LOCATION_SUCCESS",
      region: Location
    }
  | {
      type: "USER_LOCATION_FAILURE",
      error: string
    };

Обновление: Похоже, что значения longitudeDelta и latitudeDelta были проблемой. Сейчас я использую для них жестко запрограммированные значения, но я до сих пор не уверен, почему этот код работает как в одном приложении, а не в другом.

...