Cuando los geofencos no se activan en iOS, la causa es casi siempre una de una lista corta: la aplicación carece de autorización Always, el dispositivo ya estaba dentro de la región cuando la agregaste, el radio es demasiado pequeño para que iOS detecte una travesía, la aplicación alcanzó el límite de 20 regiones, o la prueba no esperó lo suficiente. El geofencinamiento de iOS funciona bien, pero informa las travesías según su propio horario. Este guía explica cómo el seguimiento de regiones decide cuándo disparar, y cómo depurar una aplicación Capacitor utilizando @capgo/background-geolocation¿Cómo funciona el seguimiento de regiones de iOS?
Cómo funciona el seguimiento de regiones de iOS
On iOS, los geofencos son CLCircularRegion objetos registrados con Core Location. Una vez registrados, el sistema operativo los monitorea, no tu aplicación. Tu aplicación puede estar suspendida o no estar ejecutándose y iOS sigue rastreando las regiones, utilizando una mezcla de torres de celulares, Wi-Fi y GPS para mantener el uso de la batería bajo.
Cuando iOS decide que el dispositivo cruzó una frontera, entrega un evento de entrada o salida a la aplicación, lanzándola en segundo plano si es necesario y permitido. Unos pocos reglas controlan esa decisión:
- iOS no informa un cruce en el momento en que el dispositivo toca la frontera. La guía de Apple es que el dispositivo debe cruzar, mover una distancia mínima más allá de la frontera y permanecer allí durante al menos unos 20 segundos antes de que se entregue el evento. Esto evita disparar en el 'jitter' de GPS.
- La precisión de la ubicación para la monitorización de regiones depende de qué radios están alrededor. En una ciudad con Wi-Fi denso, puede ser rápido. En una carretera rural, puede tomar minutos.
- Los eventos solo son para transiciones. Estar dentro de una región cuando se inicia la monitorización no cuenta como una entrada.
Configura geofencin en una aplicación Capacitor
Instala el plugin y configura las claves de iOS:
bun add @capgo/background-geolocation
bunx cap sync
<key>NSLocationWhenInUseUsageDescription</key>
<string>We use your location to detect when you arrive at a store.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We need Always access to notify you when you arrive, even when the app is closed.</string>
Luego registra regiones:
import { BackgroundGeolocation } from '@capgo/background-geolocation';
await BackgroundGeolocation.setupGeofencing({
url: 'https://api.example.com/v1/geofence-events',
headers: { Authorization: 'Bearer <token>' },
notifyOnEntry: true,
notifyOnExit: true,
payload: { userId: 'u-42' },
});
await BackgroundGeolocation.addGeofence({
identifier: 'store-paris-11',
latitude: 48.8606,
longitude: 2.3795,
radius: 150,
payload: { storeId: 'paris-11' },
});
await BackgroundGeolocation.addListener('geofenceTransition', (event) => {
console.log(`${event.transition} ${event.identifier}`, event.payload);
});
await BackgroundGeolocation.addListener('geofenceError', (event) => {
console.error('Geofence error', event.identifier, event.code, event.message);
});
setupGeofencing pregunta por la autorización que la geolocalización necesita por defecto (requestPermissions por defecto true). On iOS that means Always.
Ahora, los modos de falla.
1. No tiene autorización de Always.
La supervisión de regiones en iOS requiere autorización de Always. Con solo While Using App, sus regiones no entregarán eventos cuando la aplicación esté en segundo plano o no esté ejecutándose, lo cual es el propósito principal de una geofencia.
Verifique antes de registrar regiones, y explique la solicitud en su propia interfaz de usuario primero:
const status = await BackgroundGeolocation.checkPermissions();
if (status.backgroundLocation !== 'always' && status.backgroundLocation !== 'granted') {
// Show your own screen explaining the feature, then:
const next = await BackgroundGeolocation.requestPermissions({
permissions: ['backgroundLocation'],
});
if (next.backgroundLocation === 'when_in_use' || next.backgroundLocation === 'denied') {
await BackgroundGeolocation.openSettings();
}
}
Tenga en cuenta que iOS puede no mostrar el prompt de Always de inmediato. Los usuarios que seleccionaron "Permitir mientras se utiliza la aplicación" pueden ver el segundo prompt más tarde. Los usuarios que seleccionaron "Permitir una vez" obtienen un permiso temporal que se resetea. Si la geofenciamiento es una característica principal, verifique el estado en cada inicio de aplicación y muestre una bandera clara cuando no es Always.
2. El dispositivo ya estaba dentro de la región.
Si agrega una geofencia mientras el teléfono está dentro de ella, iOS no envía un evento de entrada. Nada cruzado. Los equipos golpean esto constantemente cuando prueban en su escritorio con una región alrededor de la oficina.
Solucione esto en su aplicación: cuando registre una región, compare la posición actual con la región y maneje "ya dentro" usted mismo.
import { Geolocation } from '@capacitor/geolocation';
function distanceMeters(lat1: number, lon1: number, lat2: number, lon2: number) {
const R = 6371000;
const toRad = (d: number) => (d * Math.PI) / 180;
const dLat = toRad(lat2 - lat1);
const dLon = toRad(lon2 - lon1);
const a =
Math.sin(dLat / 2) ** 2 +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) ** 2;
return 2 * R * Math.asin(Math.sqrt(a));
}
const region = { identifier: 'store-paris-11', latitude: 48.8606, longitude: 2.3795, radius: 150 };
await BackgroundGeolocation.addGeofence(region);
const pos = await Geolocation.getCurrentPosition({ enableHighAccuracy: true });
if (distanceMeters(pos.coords.latitude, pos.coords.longitude, region.latitude, region.longitude) < region.radius) {
handleAlreadyInside(region.identifier);
}
declare function handleAlreadyInside(id: string): void;
Para probar un evento de entrada, camine o conduzca bien más allá del radio, espere, luego regrese.
3. El radio es demasiado pequeño.
iOS acepta radios pequeños, pero la confiabilidad disminuye rápidamente por debajo de unos 100 metros, porque la supervisión de regiones se basa en Wi-Fi y posicionamiento de celda. Una región de 30 metros alrededor de la puerta de una tienda puede disparar tarde, disparar después de que el cliente ha salido, o no disparar en absoluto.
Valores prácticos:
| Uso de caso | Radio sugerido |
|---|---|
| Llegada a tienda o restaurante | 100 a 200 m |
| Oficina, campus, almacén | 150 a 300 m |
| Zona de barrio o ciudad | 500 m y más |
Si necesita precisión de nivel de puerta, combine un geofence más grande con ubicación de fondo o un beacon una vez que el usuario esté dentro. Capgo también tiene un plugin de iBeacon para proximidad interior. para proximidad interior.
4. Se alcanza el límite de 20 regiones
Una aplicación de iOS puede monitorear como máximo 20 regiones a la vez. Cuando agregas más, la inscripción falla para las adicionales y obtienes un error de monitoreo.
Usar getMonitoredGeofences() para ver qué se registra realmente, y mantener un conjunto rotativo de las regiones más cercanas:
const { regions } = await BackgroundGeolocation.getMonitoredGeofences();
console.log(`Monitoring ${regions.length} regions`, regions);
Un patrón común:
- Conserva tu lista completa de lugares en el servidor.
- Cuando el aplicativo inicia, y cuando el usuario se mueve lejos (por ejemplo, al salir de una gran ‘refrescadora’ región alrededor del usuario), obtén los 19 lugares más cercanos.
- Llamar
removeAllGeofences()Luego, agrega los 19 lugares más cercanos y un gran área centrada en el usuario. Salir de esa gran área es tu señal para refrescar.
Android permite hasta 100 geofencos por aplicación, por lo que code que funciona en Android puede fallar en iOS por esta razón sola.
5. El test fue demasiado corto o demasiado estático
iOS reports transitions only after the device has clearly crossed and stayed on the other side. If you drive through a 150 meter region at 50 km/h, you spend about 20 seconds inside it. That may not be enough.
Cuando estés probando:
- Permanezca afuera durante un minuto, luego vaya adentro y permanezca al menos un par de minutos.
- Realice la prueba con Wi-Fi encendido. Apagar Wi-Fi hace que la monitorización de regiones sea mucho menos precisa, incluso si no está conectado a ninguna red.
- No confíe en el simulador para la medición del tiempo. Utilícelo con una ruta GPX en Xcode para verificar sus manejadores, luego pruebe en un dispositivo.
6. El evento se disparó, pero su JavaScript no se ejecutó.
Cuando iOS relanza su aplicación en segundo plano por un evento de región, el plugin nativo lo recibe, pero el WebView Capacitor puede no estar cargado o puede suspenderse nuevamente rápidamente. geofenceTransition El escuchador solo dispara mientras el WebView está vivo.
Es por eso setupGeofencing acepta un urlEl plugin envía por POST la transición desde nativo code, incluyendo tu conjunto fusionado payloadmergados, por lo que su servidor lo recibe incluso cuando el JavaScript nunca se ejecuta. Los encabezados se persisten con la configuración, por lo que siguen funcionando después de un reinicio, y puede rotarlos con updateHeaders().
La entrega es de mejor esfuerzo, sin cola de reintentos. Haga que el punto de conexión sea rápido e idéntico, y registre cada solicitud durante la prueba.
7. Location Services or Background App Refresh are off
Verifica estos en el dispositivo de prueba:
- Configuración, Privacidad y Seguridad, Servicios de ubicación está activo.
- Tu aplicación está configurada para siempre.
- La ubicación precisa está activa para tu aplicación. Sin ella, las regiones pequeñas son poco fiables.
- El modo de bajo consumo está desactivado durante tus primeras pruebas. Reduce la actividad de fondo.
8. Reinicios y actualizaciones de la aplicación
iOS mantiene las regiones monitoreadas a través de lanzamientos de aplicaciones. Después de un reinicio del dispositivo, el monitoreo se reanuda una vez que el sistema está disponible, pero tu aplicación debería sincronizar nuevamente sus regiones al iniciar: compara getMonitoredGeofences() con lo que esperas y reagrega los que faltan. Haz lo mismo después de una actualización de la aplicación, y siempre que el servidor cambie la lista de lugares.
En Android, las geofencillas se eliminan después de un reinicio y en unas pocas otras situaciones (ubicación desactivada, datos de la aplicación eliminados), por lo que es necesario re-registrarse al iniciar en cualquier caso. Hacerlo en ambos sistemas mantiene la lógica simple.
9. Forzar la cierre
Si un usuario fuerza cerrar la aplicación desde el panel de aplicaciones, iOS la trata como un señal fuerte de que el usuario no quiere que la aplicación esté en ejecución. El comportamiento de relanzamiento de regiones después de una fuerza cierre ha cambiado a lo largo de las versiones de iOS. No construyas una característica que solo funcione si la aplicación se relanza después de una fuerza cierre, y pruébala en las versiones de iOS que utilizan tus usuarios.
Lista de verificación de depuración
| Verificar | ¿Cómo |
|---|---|
| La permiso es siempre | checkPermissions() devuelve always o granted for backgroundLocation |
| La región está registrada | getMonitoredGeofences() La región está registrada |
| lista el identificador | Contar desde getMonitoredGeofences() |
| Contar desde | Radio ≥ 100 m addGeofence llamadas |
| No ya está dentro | Comparar posición actual al registro |
| Los errores se registran | Escuchar a geofenceError |
| El backend recibe eventos | Establecer url dentro de setupGeofencing y registrar solicitudes |
| Prueba de movimiento real | Dejar la región completamente, esperar, volver y quedarse |
Diferencias de Android a tener en cuenta
If el mismo code funciona en Android pero no en iOS, los 20 límites de región y la exigencia de Always son las razones habituales. Si funciona en iOS pero no en Android, compruebe que agregó ACCESS_BACKGROUND_LOCATION su manifest y estableció backgroundLocation: true en setupGeofencing. El plugin no agrega esa permiso por usted, porque Google Play requiere una declaración para ubicación de fondo.
Cambios de envío
Las cadenas de permisos y la configuración nativa requieren una nueva compilación. Los listados de regiones, los valores de radio y el texto de la interfaz pueden cambiar en el servidor o enviarse a través de Capgo actualizaciones en vivoPara el seguimiento continuo en lugar de eventos de entrada y salida, consulte ¿por qué iOS detiene actualizaciones de ubicación de fondopor qué iOS detiene actualizaciones de ubicación de fondo documentation para el API completo.