现在React Native 已经有了Geolocation
Api 来获取经纬度信息,之前并没有这个方法的时候怎样来获取设备的经纬度呢?
之前我是通过封装原生模块来获取设备的经纬度的,接下来看看React Native 是怎样通过原生模块来获取经纬度的。
在React Native中,一个“原生模块”就是一个实现了“RCTBridgeModule”协议的Objective-C类,
.h 文件
#import <UIKit/UIKit.h>
#import "RCTBridgeModule.h"//头文件
@interface ViewController : UIViewController <RCTBridgeModule>
@end
为了实现RCTBridgeModule协议,你的类需要包含RCT_EXPORT_MODULE()宏。这个宏也可以添加一个参数用来指定在Javascript中访问这个模块的名字。如果你不指定,默认就会使用这个Objective-C类的名字。
#import "ViewController.h"
@implementation ViewController
RCT_EXPORT_MODULE();
@end
Callback 回调函数
原生模块支持函数参数类型。我们可以提供一个方法将数据传递给React Native RCTResponseSenderBlock
只能接受一个参数,该为传递给 React Native 回调方法的参数数组。
使用如下
RCT_EXPORT_METHOD(findEvents:(RCTResponseSenderBlock)callback)
{
NSArray *events = ...
callback(@[_longitude,_latitude]);
}
你必须明确的声明要给Javascript导出的方法,否则React Native不会导出任何方法。声明通过RCT_EXPORT_METHOD()宏来实现:
RCT_EXPORT_METHOD(getLocationCount:(NSDictionary *)options
callback: (RCTResponseSenderBlock)callback){
if ([CLLocationManager locationServicesEnabled]) {
_lm = [[CLLocationManager alloc]init];
_lm.delegate = self;
// 最小距离
_longitude=@"";
_latitude = @"";
self.lm.distanceFilter=kCLDistanceFilterNone;
_lm.delegate = self;
[_lm requestWhenInUseAuthorization];
[self.lm startUpdatingLocation];
}else{
NSLog(@"定位服务不可用");
}
//保存回调函数
_block = callback;
}
.m文件
#import <UIKit/UIKit.h>
#import "ViewController.h"
// 定位需要导入的头文件
#import <CoreLocation/CoreLocation.h>
@interface ViewController () <CLLocationManagerDelegate>//遵循协议
@property (nonatomic,copy) NSString * latitude; //纬度
@property (nonatomic,copy) NSString * longitude;//经度
@property (strong,nonatomic) CLLocationManager *lm;
@property (nonatomic,strong) RCTResponseSenderBlock block;//用来保存回调的Block
@end
@implementation ViewController
RCT_EXPORT_MODULE();//为了实现RCTBridgeModule协议,你的类需要包含RCT_EXPORT_MODULE()宏
////这个宏也可以添加一个参数用来指定在Javascript中访问这个模块的名字。如果你不指定,默认使用这个OC类的名字
- (void)viewDidLoad {
[super viewDidLoad];
}
//代理方法 获取到新定位信息是调用
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation{
[NSString stringWithFormat:@"[%f,%f]",newLocation.coordinate.latitude,newLocation.coordinate.longitude];
_latitude = [NSString stringWithFormat:@"%f",newLocation.coordinate.latitude];
_longitude = [NSString stringWithFormat:@"%f",newLocation.coordinate.longitude];
NSLog(@"%@", [NSString stringWithFormat:@"[%f,%f]",newLocation.coordinate.latitude,newLocation.coordinate.longitude]);
[self.lm stopUpdatingLocation];
if (![_longitude isEqualToString:@""] && ![_latitude isEqualToString:@""])
{
//获取到经纬度,通过回调函数传值给React Native
_block(@[_longitude,_latitude]);
_lm.delegate = nil;
}
}
//获取当前的经纬度
RCT_EXPORT_METHOD(getLocationCount:(NSDictionary *)options
callback: (RCTResponseSenderBlock)callback){
if ([CLLocationManager locationServicesEnabled]) {
_lm = [[CLLocationManager alloc]init];
_lm.delegate = self;
// 最小距离
_longitude=@"";
_latitude = @"";
self.lm.distanceFilter=kCLDistanceFilterNone;
_lm.delegate = self;
// 一个是requestAlwaysAuthorization,一个是requestWhenInUseAuthorization
// [_lm requestAlwaysAuthorization];//这句话ios8以上版本使用。
[_lm requestWhenInUseAuthorization];
[self.lm startUpdatingLocation];
}else{
NSLog(@"定位服务不可利用");
}
_block = callback;
}
@end
在React Native 中我们可以这样调用
var ViewController = require('react-native').NativeModules.ViewController;
ViewController.getLocationCount({},(_longitude,_latitude)=>{
console.log(_longitude);
console.log(_latitude);
})
需要注意的是在使用定位的时候要在info.plist 中添加
<key>NSLocationAlwaysUsageDescription</key>
<string>需要您同意</string>
<key>NSLocationUsageDescription</key>
<string>需要您同意</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>需要您同意</string>