Flutter--高德地图PIO搜索插件iOS端

366 阅读2分钟

flutter与native之间可以通过Platform Channels 通信方式

  • MethodChanel:用于传递方法调用(method invocation)用来调用native中方法
  • EventChannel:用于数据流(event streams)的通信。
  • BasicMessageChannel:用于传递字符串和半结构化的信息

flutter与native直接的交互方式和h5与native交互方式比较相似,下面通过PIO搜索插件封装说明下flutter与iOS交互。

PIO搜索插件

文件目录

  • AMapFlutterSearchPlugin:编写OC调用高德地图搜索方法,处理PIO搜索结果处理
  • AMapFlutterStreamManager:数据流单例,用于传递PIO搜索结果
  • AMapFlutterSearchRegistran:注册搜索插件
  • amap_search_util.dart:高德搜索Flutter插件入口类

iOS端编码

  • AppDelegate:在appDelegate中注册插件
[AMapFlutterSearchRegistran registerWithRegistry:self];
  • AMapFlutterSearchRegistran:调用flutter插件注册方法,registerWithRegistrar:
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry> *)registy {

    [AMapFlutterSearchPlugin registerWithRegistrar:[registy registrarForPlugin:@"AMapFlutterSearchPlugin"]];

}

AMapFlutterSearchPlugin高德PIO搜索插件

  • 实现FlutterPlugin代理方法,注册MethodChanel的keyamap_flutter_search,注册EventChannel的keyamap_flutter_search_stream
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
    FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"amap_flutter_search" binaryMessenger:[registrar messenger]];

    AMapFlutterSearchPlugin *instance = [[AMapFlutterSearchPlugin alloc] init];

    [registrar addMethodCallDelegate:instance channel:channel];

    FlutterEventChannel *eventChanel = [FlutterEventChannel eventChannelWithName:@"amap_flutter_search_stream" binaryMessenger:[registrar messenger]];

    [eventChanel setStreamHandler:[[AMapFlutterStreamManager sharedInstance] streamHandler]];

}

// 响应flutter调用Native方法
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
    if ([@"AMapInputTipsSearch" isEqualToString:call.method]) {
        [self searchTipsWithKey:call.arguments];
    }
}
  • searchTipsWithKey:编写iOS调用高德搜索接口
- (void)searchTipsWithKey:(NSDictionary *)searchDict {
    NSString *keywords = [searchDict objectForKey:@"keywords"];
    
    if (keywords.length == 0) {
       return;
    }

    AMapInputTipsSearchRequest *tips = [[AMapInputTipsSearchRequest alloc] init];
    tips.keywords = keywords;
    [self.searchAPI AMapInputTipsSearch:tips];
}
  • onInputTipsSearchDone:搜索结果代理方法,返回搜索结果
- (void)onInputTipsSearchDone:(AMapInputTipsSearchRequest *)request response:(AMapInputTipsSearchResponse *)response {
    // Stream传递给flutter
    [self handleAMapSearchResult:response.tips];
}
  • handleAMapSearchResult:处理搜索结果,通过StreamManager进行数据传递
- (**void**)handleAMapSearchResult:(NSArray<AMapTip *> *)tips {
    NSMutableArray *array = [NSMutableArray array];

    [tips enumerateObjectsUsingBlock:^(AMapTip * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        [dict setObject:obj.name.length > 0 ? obj.name : @"" forKey:@"name"];
        [dict setObject:obj.address.length > 0 ? obj.address : @"" forKey:@"address"];
        [dict setObject:[NSString stringWithFormat:@"%f",obj.location.latitude] forKey:@"latitude"];
        [dict setObject:[NSString stringWithFormat:@"%f",obj.location.longitude] forKey:@"longitude"];
        [array addObject:dict];
    }];
    
    NSDictionary *resultDict = @{
        @"results" : array
    };
    
    [[AMapFlutterStreamManager sharedInstance] streamHandler].eventSink(resultDict);
}

Flutter编码---AMapFlutterSearch高德搜索Flutter插件入口类

  • 注册MethodChannelEventChannel,注册的key需要与iOS使用的key保持一致。
static const MethodChannel _methodChannel = const MethodChannel(_CHANNEL_METHOD_SEARCH);
static const EventChannel _eventChannel = const EventChannel(_CHANNEL_STREAM_SEARCH);
  • Stream<Map<String, Object>> _onSearchResults:监听数据流。
static Stream<Map<String, Object>> _onSearchResults = _eventChannel
    .receiveBroadcastStream()
    .asBroadcastStream()
    .map<Map<String, Object>>((element) => element.cast<String, Object>());

StreamController<Map<String, Object>>? _receiveStream;


Stream<Map<String, Object>> onSearchResults() {
  if (_receiveStream == null) {
    _receiveStream = StreamController();
    _subscription = _onSearchResults.listen((Map<String, Object> event) {
      Map<String, Object> newEvent = Map<String, Object>.of(event);
      _receiveStream?.add(newEvent);
    });
  }
  return _receiveStream!.stream;
}
  • 调用Native搜索方法: key值需要与Native中保持一致
void searchTipsWithKey(Map<String, dynamic> searchDict) {

  _methodChannel.invokeMethod('AMapInputTipsSearch', searchDict);
  
}