swift – react native – create location monitoring library for iOS

swift – react native – create location monitoring library for iOS


I’m researching on creating library for react native new arch. In the meanwhile, I’m coping with create-react-native-library to create a location monitoring lib for iOS for higher customization.

I’m new to each Goal-C and Swift, so actually want your helps.

My present model:

  • create-react-native-library: 0.48.3
  • react-native: 0.78.0

My iOS mission already has:

  • background location monitoring allow
  • information.plist with:
    • NSLocationWhenInUseUsageDescription
    • NSLocationAlwaysUsageDescription
    • NSLocationAlwaysAndWhenInUseUsageDescription

On simulator, app settings:

  • Location monitoring set to All the time enable
  • Checked on Maps app and the blue dot is transferring.

Please discover code beneath

MyLocationTracking.h

#import "generated/RNMyLocationTrackingSpec/RNMyLocationTrackingSpec.h"

@interface MyLocationTracking : NativeMyLocationTrackingSpecBase 

@finish

MyLocationTracking.mm

#import 

#import "MyLocationTracking.h"
#import "MyLocationTracking-Swift.h"

@implementation MyLocationTracking
RCT_EXPORT_MODULE()

- (void)setInfo:(nonnull NSString *)baseURL token:(nonnull NSString *)token pushGPSInterval:(double)pushGPSInterval pushGPSDistance:(double)pushGPSDistance integrationId:(nonnull NSString *)integrationId {
  
  MyLocationTrackingImpl *swiftInstance = [MyLocationTrackingImpl shared];
  
  [swiftInstance setInfo:baseURL
                 rnToken:token
       rnPushGPSInterval:pushGPSInterval
       rnPushGPSDistance:pushGPSDistance
         rnIntegrationId:integrationId
                callback:^(NSDictionary *locationData) {
    [self emitOnLocationChanged:locationData];
  }];
}

- (nonnull NSNumber *)isProviderEnabled {
  return @1;
}


- (nonnull NSNumber *)isServiceRunning {
  return @1;
}


- (void)startWatchLocation {
  [[MyLocationTrackingImpl shared] startWatchLocation];
}


- (void)stopWatchLocation {
  [[MyLocationTrackingImpl shared] stopWatchLocation];
}


- (void)updateIntegrationId:(nonnull NSString *)integrationId {
  [[MyLocationTrackingImpl shared] updateIntegrationId:integrationId];
}


- (std::shared_ptr<:react::turbomodule>)getTurboModule:
(const fb::react::ObjCTurboModule::InitParams &)params
{
  return std::make_shared<:react::nativemylocationtrackingspecjsi>(params);
}

@finish

MyLocationTrackingImpl.swift: That is working as a bridge to attach the core Location Monitoring with the Goal C

import Basis

@objc
public class MyLocationTrackingImpl: NSObject {
  
  personal let myLocationTrackingCore = MyLocationTrackingCore()

  // Singleton occasion
  @objc public static let shared = MyLocationTrackingImpl()
  
  // Personal initializer to implement singleton
  personal override init() {
    tremendous.init()
    print("=== MySingleton initialized! ===") 
  }
  
  @objc public func setInfo(_ baseURL: String, rnToken token: String, rnPushGPSInterval pushGPSInterval: Double, rnPushGPSDistance pushGPSDistance: Double, rnIntegrationId integrationId: String, callback: @escaping ([String: Any]) -> Void) {
    myLocationTrackingCore.setInfo(baseURL, rnToken: token, rnPushGPSInterval: pushGPSInterval, rnPushGPSDistance: pushGPSDistance, rnIntegrationId: integrationId, callback: callback)
  }

  @objc public func startWatchLocation() {
    myLocationTrackingCore.startWatchLocation()
  }
  
  @objc public func stopWatchLocation() {
    myLocationTrackingCore.stopWatchLocation()
  }
  
  @objc public func updateIntegrationId(_ integrationId: String) {
    print("Up to date Integration ID: (integrationId)");
  }
}

MyLocationTrackingCore.swift

import Basis
import CoreLocation

class MyLocationTrackingCore: NSObject, CLLocationManagerDelegate {
  
  var locationManager : CLLocationManager = CLLocationManager()
  
  var BASE_URL : String = ""
  var token : String = ""
  var pushGPSInterval : Double = 10_000
  var pushGPSDistance : Double = 0
  var integrationId : String = "{}"
  
  var pushGPSTimer: Date = Date()
  
  var locationCallback: (([String: Any]) -> Void)?
  
  func setInfo(_ baseURL: String, rnToken token: String, rnPushGPSInterval pushGPSInterval: Double, rnPushGPSDistance pushGPSDistance: Double, rnIntegrationId integrationId: String, callback: @escaping ([String: Any]) -> Void) {
    print("= Initializing....");
    self.BASE_URL = baseURL
    self.token = token
    self.integrationId = integrationId
    
    // The minTime is in millisecond, right here we want second
    self.pushGPSInterval = (pushGPSInterval == 0 ? 10_000 : pushGPSInterval) / 1_000
    self.pushGPSDistance = pushGPSDistance < 0 ? 0 : pushGPSDistance
    
    // Callback
    self.locationCallback = callback
    
    print("Base url         : (self.BASE_URL)");
    print("token            : (self.token)");
    print("integrationId    : (self.integrationId)");
    print("pushGPSInterval  : (self.pushGPSInterval)");
    print("pushGPSDistance  : (self.pushGPSDistance)");
    print("set off callback :");
    
    // Callback: attempt ship knowledge
    if let locationCallback = self.locationCallback {
      let newLocationData: [String: Any] = [
        "lat": 37.7859,
        "lng": -122.4364,
        "alt": 15.0,
        "spd": 6.0,
        "course": 45.0
      ]
      locationCallback(newLocationData)
      print("- Location Callback triggered")
    } else {
      print("= Location Callback is nil")
    }
    
    // Init Location Supervisor
    self.locationManager.delegate = self
    self.locationManager.distanceFilter = self.pushGPSDistance
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
    self.locationManager.requestWhenInUseAuthorization()
    self.locationManager.requestAlwaysAuthorization()
    self.locationManager.allowsBackgroundLocationUpdates = true
    self.locationManager.pausesLocationUpdatesAutomatically = false
    self.locationManager.activityType = .automotiveNavigation
    
    print("= Initialized");
  }
  
  func startWatchLocation() {
    if CLLocationManager.locationServicesEnabled() {
      self.pushGPSTimer = Date().addingTimeInterval(0)
      self.locationManager.startUpdatingLocation()
      print("Begin location Location");
    }
  }
  
  func stopWatchLocation() {
    if CLLocationManager.locationServicesEnabled() {
      self.locationManager.stopUpdatingLocation()
      self.locationManager.delegate = nil
      print("Cease location monitoring")
    }
  }
  
  func locationManager(
    _ supervisor: CLLocationManager,
    didUpdateLocations areas: [CLLocation]
  ) {
    if let userLocation = areas.final {
      let latitude = String(userLocation.coordinate.latitude)
      let longitude = String(userLocation.coordinate.longitude)
      let altitude = String(userLocation.altitude)
      let pace = String(userLocation.pace)
      let course = String(userLocation.course)
      
      print("===============")
      print("person latitude = (latitude)")
      print("person longitude = (longitude)")
      print("person altitude = (altitude)")
      print("person pace = (pace)")
      print("person course = (course)")
    } else {
      print("===============")
      print("No legitimate location knowledge acquired")
    }
  }
  
  func locationManager(
    _ supervisor: CLLocationManager,
    didFailWithError error: Error
  ) {
    print("===============")
    print("Error = (error)")
  }
}

In the meanwhile, the lib can:

  • Name Swift’s methodology from Goal-C accurately.
  • when startWatchLocation in MyLocationTrackingCore.swift execute, there’s a location monitoring icon on the highest left of iOS simulator
  • when stopWatchLocation in MyLocationTrackingCore.swift execute, the icon is gone

The problem is:

  • func locationManager: didUpdateLocations and didFailWithError usually are not triggered, no print methodology is executed.

Please let me know you probably have any concepts about why the didUpdateLocations and didFailWithError usually are not triggered.

Should you want any info, please additionally let me know.

Many thanks, guys!

Leave a Reply

Your email address will not be published. Required fields are marked *