5自定义地理位置pod插件201903

前言:
1.制作自定义插件,获取地理位置信息,包括城市区域和街道名
2.oc写原生代码,暴露接口,提供给weex调用

开发环境:xcode10
开发平台:ios和weexeros

一.本地引入自己制作的pod
1.修改Podfile文件,增加 pod 'CJNativeCodeForWeexEros', :path=>'./CJNativeCodeForWeexEros/'

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
#忽略引入库的警告
inhibit_all_warnings!

def common
    #WeexSDK
    pod 'WeexSDK', :git => 'https://github.com/bmfe/incubator-weex.git'
    #Weex debugger 调试工具,只在开发模式集成
    pod 'WXDevtool', :git => 'https://github.com/bmfe/weex-devtool-iOS.git', :configurations => ['Debug']
    #Eros iOS 基础库
    pod 'ErosPluginBaseLibrary', :git => 'https://github.com/bmfe/eros-plugin-ios-baseLibrary.git', :tag => '1.3.5'

    #Other Plugins
    pod 'CJNativeCodeForWeexEros', :path=>'./CJNativeCodeForWeexEros/'

    end

target 'WeexEros' do
    common

end

因为是本地引入,不是加载远程仓库的,所以需要把代码放到Podfile同级目录


图片.png

2.查看podspec文件,确保路径正确

 Pod::Spec.new do |s|

   s.name             = "CJNativeCodeForWeexEros"    #插件名称
   s.version          = "1.0.4"             #版本号
   s.summary          = "Just Testing."     #简短介绍,下面是详细介绍
   s.description      = <<-DESC
                        Testing Private Podspec.
                        * Markdown format.
                        * Don't worry about the indent, we strip it!
                        DESC

   s.homepage         = "https://github.com/cj2527/CJNativeCodeForWeexEros"  #主页,这里要填写可以访问到的地址,不然验证不通过
   s.license          = 'MIT'              #开源协议
   s.author           = { "appleJun" => "cj2527@163.com" } #作者信息
   s.source           = { :git => "https://github.com/cj2527/CJNativeCodeForWeexEros.git", :tag => s.version.to_s }      #项目地址,这里不支持ssh的地址,验证不通过,只支持HTTP和HTTPS,最好使用HTTPS
   s.platform     = :ios, '8.0'            #支持的平台及版本
   s.requires_arc = true                   #是否使用ARC,如果指定具体文件,则具体的问题使用ARC

   s.source = { :git => 'https://github.com/cj2527/CJNativeCodeForWeexEros.git', :tag => s.version.to_s }
s.resources = 'CJNativeCodeForWeexEros/*'
s.source_files = "CJNativeCodeForWeexEros/*.{h,m,mm}"
   s.frameworks = 'UIKit'                  #所需的framework,多个用逗号隔开
 

 end

注意s.resources = 'CJNativeCodeForWeexEros/'
s.source_files = "CJNativeCodeForWeexEros/
.{h,m,mm}"
表示引入自己制作pod插件的CJNativeCodeForWeexEros目录下及子目录所有文件

图片.png

3.pod update一下


图片.png

二、原生代码获取具体地址信息,提供接口供weex调用
CJLocationManager.h代码如下

//
//  CJTLocationManager.h
//  修改JYTTLocationManager而来,用来拓展获取具体的地理位置信息

#import <Foundation/Foundation.h>

typedef void(^CurrentLocationBlock)(NSString *lon, NSString *lat,NSString *city,NSString *subLocality,NSString *street);

@interface CJLocationManager : NSObject

+ (instancetype)shareInstance;

/**
 *  获取当前坐标
 *
 *  @param block 返回经纬度
 */
- (void)getCurrentLocation:(CurrentLocationBlock)block;

/**
 *  获取上一次定位信息
 *
 *  @param block 返回上一次定位的信息
 */
- (void)getCacheLocation:(CurrentLocationBlock)block;

@end

CJLocationManager.m代码如下

//
//  JYTLocationManager.m
//  JingYitong
//
//  Created by XHY on 16/5/26.
//  Copyright © 2016年 XHY. All rights reserved.
//

#import "CJLocationManager.h"
#import <CoreLocation/CoreLocation.h>
#import "TransformCLLocation.h"
#import <UIKit/UIKit.h>
#import "WeexSDK.h"
@interface CJLocationManager () <CLLocationManagerDelegate>
{
    CLLocationManager *_locationManager;
    NSTimer *_timer;
}
@property (nonatomic, strong) CLLocationManager *locationManager;
@property (nonatomic, copy) CurrentLocationBlock currentLocationBlock;

@property (nonatomic, copy) NSString *cacheLng;
@property (nonatomic, copy) NSString *cacheLat;
@property (nonatomic, copy) NSString *cacheCity;
@property (nonatomic, copy) NSString *cacheSubLocality;
@property (nonatomic, copy) NSString *cacheStreet;


@end

@implementation CJLocationManager


+ (instancetype)shareInstance
{
    static CJLocationManager *_instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!_instance) {
            _instance = [[CJLocationManager alloc] init];
        }
    });
    return _instance;
}

- (CLLocationManager *)locationManager
{
    if (!_locationManager) {
        //定位管理器
        _locationManager=[[CLLocationManager alloc]init];
        //设置代理
        _locationManager.delegate = self;
        //设置定位精度
        _locationManager.desiredAccuracy=kCLLocationAccuracyBest;
        
        
        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
            [_locationManager requestWhenInUseAuthorization];
        }
    }
    return _locationManager;
}

- (void)updateCurrentLocation
{
    if (![CLLocationManager locationServicesEnabled]) {
        
        WXLogInfo(@"定位服务当前可能尚未打开,请设置打开!");
        
        [self callBackWithLongitude:nil latitude:nil city:nil subLocality:nil street:nil];
        
        return;
    }
    
    /* 如果没有授权或者受限制返回nil */
    if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusRestricted || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
        
        [self callBackWithLongitude:nil latitude:nil city:nil subLocality:nil street:nil];
        
        
        return;
    }
    
    //启动跟踪定位
    [self.locationManager startUpdatingLocation];
}

- (void)timerAction
{
    [self callBackWithLongitude:nil latitude:nil city:nil subLocality:nil street:nil];
    
}

#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
    CLLocation *location = [locations firstObject]; //取出第一个位置
    
    /* 将gps坐标系转换成gcj-02坐标系 */
    CLLocationCoordinate2D coordinate = [TransformCLLocation wgs84ToGcj02:location.coordinate];
    [self.locationManager stopUpdatingLocation];
    
    //反向地理编码
    
    CLGeocoder *clGeoCoder = [[CLGeocoder alloc] init];
    
    CLLocation *cl = [[CLLocation alloc] initWithLatitude:coordinate.latitude longitude:coordinate.longitude];
    __block  NSString *city=@"";
    __block  NSString *subLocality = @"";
    __block NSString *street = @"";
   
    [clGeoCoder reverseGeocodeLocation:cl completionHandler: ^(NSArray *placemarks,NSError *error) {
       
        for (CLPlacemark *placeMark in placemarks) {
            
            NSDictionary *addressDic = placeMark.addressDictionary;
            
            NSString *state=[addressDic objectForKey:@"State"];
            
            city=[addressDic objectForKey:@"City"];
            
            subLocality=[addressDic objectForKey:@"SubLocality"];
            
            street=[addressDic objectForKey:@"Street"];
            
            NSLog(@"所在城市====%@ %@ %@ %@", state, city, subLocality, street);
            [self callBackWithLongitude:[NSString stringWithFormat:@"%f",coordinate.longitude] latitude:[NSString stringWithFormat:@"%f",coordinate.latitude] city:city subLocality:subLocality street:street];
            
            [self.locationManager stopUpdatingLocation];
            
        }
    }];
}


/**
 *  回调方法把经纬度通过block回传
 *
 *  @param lng 经度
 *  @param lat 纬度
 */
- (void)callBackWithLongitude:(NSString *)lng latitude:(NSString *)lat city:(NSString *)city subLocality:(NSString *)subLocality street:(NSString *)street
{
    // 缓存位置信息
    self.cacheLng = lng;
    self.cacheLat = lat;
    
    if (_timer) {
        [_timer invalidate];
        _timer = nil;
    }
    if (self.currentLocationBlock) {
        self.currentLocationBlock(lng, lat,city,subLocality,street);
        _currentLocationBlock = nil;
    }
}

#pragma mark Public Method
- (void)getCurrentLocation:(CurrentLocationBlock)block
{
    if (_timer) {
        [_timer invalidate];
        _timer = nil;
    }
    
    _timer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(timerAction) userInfo:nil repeats:NO];
    
    self.currentLocationBlock = block;
    [self updateCurrentLocation];
}

- (void)getCacheLocation:(CurrentLocationBlock)block
{
    // 判断如果有缓存信息直接返回,无缓存则实时获取一次
    if (self.cacheLng && self.cacheLng.length > 0 && self.cacheLat && self.cacheLat.length > 0) {
        block(self.cacheLng,self.cacheLat,self.cacheCity,self.cacheSubLocality,self.cacheStreet);
    } else {
        [self getCurrentLocation:block];
    }
}
@end

然后在CJTest.h文件遵守协议

#import <Foundation/Foundation.h>
#import "WeexSDK.h"
@interface CJTest : NSObject <WXModuleProtocol>

@end

.m文件实现

//
//  CJTest.m
//  CJNativeCodeForWeexEros
//
//  Created by appleJun on 2019/3/15.
//  Copyright © 2019 appleJun. All rights reserved.
//

#import "CJTest.h"
#import "CJLocationManager.h"
#import "NSDictionary+Util.h"
@implementation CJTest

@synthesize weexInstance;
WX_EXPORT_METHOD(@selector(getGeolocation:))
- (void)getGeolocation:(WXModuleCallback)callback
{
    
    [[CJLocationManager shareInstance] getCurrentLocation:^(NSString *lon, NSString *lat,NSString *city,NSString *subLocality,NSString *street) {
        if (callback) {
            
            NSInteger resCode = BMResCodeError;
            NSDictionary *data = nil;
            if (lon && lat) {
                resCode = BMResCodeSuccess;
                data = @{@"locationLat": lat,@"locationLng": lon,@"city":city,@"subLocality":subLocality,@"street":street};
            }
            
            /* 构建callback数据 */
            NSDictionary *resultData = [NSDictionary configCallbackDataWithResCode:resCode msg:nil data:data];
            
            callback(resultData);
            
        }
    }];
}

 
@end

3.注册Modules


图片.png

最后发现也是坑,一旦pod update,代码也会重置,
所以还是自动注册的好

#import <WeexPluginLoader/WeexPluginLoader/WeexPluginLoader.h>
// 第一个参数为暴露给 js 端 Module 的名字,
// 第二个参数为你 Module 的类名
WX_PlUGIN_EXPORT_MODULE(@"cjCommon", CJTest)

三、修改weex代码


图片.png

1.src目录下增加cj.js文件,代码就模仿geo.js写

const cj = weex.requireModule('cjCommon')
const Cj = Object.create(null)

Cj.install = (Vue) => {
    Vue.prototype.$cj = {
        get () {
            return new Promise((resolve, reject) => {
                cj.getGeolocation(({ status, errorMsg, data }) => {
                    status === 0 ? resolve(data) : reject({ status, errorMsg, data })
                })
            })
        }
    }
}

Vue.use(Cj)

2.config目录下打开index.js文件


图片.png

增加代码引入js
import '../widgets/src/cj'


图片.png

3.就可以用this引用使用了

               this.$cj.get().then(
     
                data => {
                   
                    this.selectedCity = data.city+data.street
                    console.log('city====',data.city)
                },
                error => {
                    this.$notice.toast({
                        message: '获取位置失败'
                    });
                    console.log(error);
                }
            );

推荐阅读更多精彩内容