iOS的 gRPC 之路

栏目: 服务器 · 发布时间: 5年前

内容简介:作者: iOS 团队 - 王玎##为什么要用?##我们的期望

作者: iOS 团队 - 王玎

##为什么要用?

  • 网络层代码直接按照定义好的proto 文件生成,简单方便
  • 而从用户角度来看,可以节省流量,网络请求速度更快了
  • 翁伟要求的

##我们的期望

  • 支持 swift,有 swift 实现
  • 使用简单
  • 方便维护

##现实情况

  • 只有 oc的 release 版本
  • 需要创建 podspec 文件,通过这个文件来管理和生成 grpc 的客户端文件以及安装依赖库
  • 每次使用都需要创建 Service 实例
  • 不支持 Int 类型,如果要使用需要添加一定的代码进行转换
  • 网络请求的回调格式不符合我们里面的代码风格
grpc的:[service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { if (response) { NSLog(@"Finished successfully with response:\n%@", response); } else if (error) { NSLog(@"Finished with error: %@", error); } }];

我们的:public class func getHomePageShowArea(success: @escaping ([TRHomePageArea]) -> Void, failure: ((Error) -> Void)? = nil)

##怎么办? ###鉴于上述情况,我们有了以下的方案 通过 NS_REFINED_FOR_SWIFT 这个宏所标记的函数、方法和变量在 Obj-C 代码中可以正常使用,但当它们桥接到 Swift 的时候,名称前面就会加上“__”。通过在 Obj-C 代码中使用这个宏,我们就可以在 Swift 代码中使用相同的名称来提供一个更便于使用的 API ,就像下面这样:

iOS的 gRPC 之路
iOS的 gRPC 之路
iOS的 gRPC 之路
iOS的 gRPC 之路

但是,对于每一个生成的文件,极大的可能都会有一个这种转换文件与之对应。这会造成运行时的体积增大,工程体积增大。

###现在的方案swift-grpc

现有的资源: grpc-swift: github.com/grpc/grpc-s… swift-protobuf: github.com/apple/swift…

问题:

  • 没有可用的 release 版本
  • 有写好的模板代码,但是没有生成工具
  • 没有集成方式的示例
  • swift-protobuf生成的是 struct而不是 class

####初始的想法

由于 grpc-objc 是确定可以使用的,那么是不是可以使用 swift 的代码来完全替代生成的 oc代码,初步看来好像是可行的:

  • service的代码按照oc的代码的直接翻译,message 直接使用 swift-protobuf 代替:
iOS的 gRPC 之路

将上面的代码翻译成 swift 是一件很简单的事,这里就不说了,值得注意的是这个地方,它需要传入的是一个 class类型, 而我们的 swift-protobuf只提供 struct, 这就尴尬了:

responseClass:[Template class]

接下来直接改 swift-protobuf 的编译器,让它生成 class 是不 是就可以了?经过实践的证明,它远远不是改一下编译器那么简单的事情,在 swift-protobuf runtime library 中还需要我们提供一个对 class 的序列化,看了下它们实现,

iOS的 gRPC 之路

完全不知道怎么写这样一个东西。到这里这个想法已经进行不下去了,那再换一种吧。

####想法ing

既然有 grpc-swift,而且给出的有可运行 example, 通过验证,这个代码也是可行的(service是手动写的,messae部分使用 swift-protobuf 生成),可以从服务器请求和接收数据,可以满足我们工程中的需要。

有了上述的支持,我们现在只需要一个 service 代码 compiler 就可以了,做为一个没有用过 c++的怎么来改写/编写这样一个 compiler,就不在这里说了,各种坑是肯定的了。

有了service 代码 compiler之后,这个方案可以算是完成了一半了。

接下来就可以看看怎么集成到我们的工程中使用了,由于 grpc-swift 中是直接将需要的依赖库拖到工程中使用的,但是这种方式并不是我们想要的,是不是可以使用 grpc-objc 的方式(pod install)来集成?

研究了 grpc-objc 的和 grpc-swift 之后,发现想要使用 grpc-swift需要 CgRPC(为了支持 swift对grpc-Core 的封装和拓展),SgRPC(使用 swift进行封装)这两个库支持,踩了 N 多坑之后,终于将这两个库弄成了本地 pod repo。

接下就可以集成到我们的 ezbuy 工程里了,但是事情总是没有那么顺利,pod install 之后工程果断编译报错,经过查找最后发现是由于在 grpc-Core 里定义了一个和系统库重名string.h 文件(他们在 podspec 文件中说是故意定义成这样的),而第三方库HappyDNS 中使用了#include "string.h" 这样的一种方式(不是标准的方式)来引用系统库中 string.h 文件,从而导致了报错,至于错误原因在这里就不说了,修改成 #include <string.h> 这样之后,编译通过。

完成了这两个库的安装后,终于可以进入正题了。创建

iOS的 gRPC 之路

我们工程的 podspec 文件来进行集成使用了。由于前面的研究,我们生成代码需要的是这三个工具:

iOS的 gRPC 之路

由于这三个 工具 是经过代码修改生成的,所以我们必须修改 podspec 文件来指定使用这三个工具,由于没有保存那个版本,所以就不展示了,有需要的可以联系我。

大功告成!!2333333333

再测试一下,生成一个带有引用文件,比如这个

iOS的 gRPC 之路

pod install 之后果断报错啊,

iOS的 gRPC 之路

通过一番查找尝试,原来还要指定搜索参数。然后就有了以下的 shell 脚本grpc.sh(边搜边写,求不吐槽)和修改后的 podspec:

#####grpc.sh

#! /bin/sh
#! /bin/bash

#定义需要搜索的目录路径,如果.proto 文件放置的位置有改变,需要更改这个地方的路径
declare targetSearchPath=apidoc/ios_proto

if [[ ! -f "/usr/local/lib/libprotobuf.10.dylib" ]]; then
 echo "请按照grpcInstall.md文件安装 grpc & protobuf"
 open grpcInstall.md
fi

if [[ ! -d "$targetSearchPath" ]]; then
 echo "$targetSearchPath 不存在,请确认.proto 文件的放置路径。"
fi

# 导入环境变量,以便 protoc 和 protoc-gen-swift 的使用
export PATH=$PATH:./grpc

#定义接收搜索参数的变量"-I xxxx -I xxxxx -I xxxxx"
declare protoPath=""

function getProtoSearchPath() {

 fList=`ls $1`

 for folder in $fList
 do
  temp=${1}"/"${folder}
  # echo "当前搜索的目录是:$temp"
  if [[ -d $temp ]]; then
   protoPath=${protoPath}" -I $temp"
   # echo "The directory is>> $protoPath"
   getProtoSearchPath $temp $protoPath
  fi
 done
}

getProtoSearchPath $targetSearchPath

#Path where protoc and gRPC plugin
protoc="grpc/protoc"
plugin="grpc/grpc_swift_plugin"

#name of pod spec
name="ezbuyGRPC"
pod_root=Pods

# Directory where the generated files will be placed.
generated_path=$pod_root"/"$name

mkdir -p $generated_path

protoPath=$protoPath" -I $targetSearchPath"
p_command="${protoc} --plugin=protoc-gen-grpc=$plugin --swift_out=$generated_path --grpc_out=$generated_path $protoPath $targetSearchPath/*/*.proto"
echo $p_command
eval $p_command
复制代码

#####ezbuyGRPC.podspec

#
#  Be sure to run `pod spec lint ezbuyGRPC.podspec' to ensure this is a
#  valid spec and to remove all comments including this before submitting the spec.
#
#  To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
#  To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
#

Pod::Spec.new do |s|

  s.name         = "ezbuyGRPC"
  s.version      = "0.0.3"
  s.summary      = "This is useful to install grpc easily."
  s.description  = <<-DESC
                    Use 'pod install' to generate proto files.
                    When you change the proto file and want to use 'pod install', you should change the property of version in this file.
                   DESC

  s.homepage     = "http://www.grpc.io/"

  s.author             = { "wangding" => "wangding@ezbuy.com" }

  s.ios.deployment_target = "8.0"
  s.osx.deployment_target = "10.9"

  s.source       = { :path => "."}


  # Base directory where the .proto files are.
  # src = "apidoc/proto/*"

  # Pods directory corresponding to this app's Podfile, relative to the location of this podspec.
  pods_root = 'Pods'

  # Path where Cocoapods downloads protoc and the gRPC plugin.
  # protoc_dir = "."
  # protoc = "#{protoc_dir}/protoc"
  # plugin = "./grpc_swift_plugin"


  # swift_protoc_plugin = "protoc-gen-swift"

  # Directory where the generated files will be placed.
  dir = "#{pods_root}/#{s.name}"

  # s.prepare_command = <<-CMD
  #   rm -f /usr/local/bin/#{swift_protoc_plugin}
  #   cp #{swift_protoc_plugin} /usr/local/bin/
  #   mkdir -p #{dir}
  #   #{protoc} \
  #   --plugin=protoc-gen-grpc=#{plugin} \
  #   --swift_out=#{dir} \
  #   --grpc_out=#{dir} \
  #   -I #{src} \
  #   -I #{protoc_dir} \
  #   -I #{src}/* \
  #   #{src}/*.proto
  # CMD

    s.prepare_command = <<-CMD
      chmod 777 grpc/grpc.sh
      ./grpc/grpc.sh
    CMD

  # Files generated by protoc
  s.subspec "Messages" do |ms|
  ms.source_files = "#{dir}/*.pb.swift"
  ms.header_mappings_dir = dir
  ms.requires_arc = true
  # The generated files depend on the protobuf runtime. The version is 0.9.24
  ms.dependency "SwiftProtobuf"
  end

  # Files generated by the gRPC plugin
  s.subspec "Services" do |ss|
  ss.source_files = "#{dir}/*.pbrpc.swift"
  ss.header_mappings_dir = dir
  ss.requires_arc = true
  # The generated files depend on the gRPC runtime, and on the files generated by protoc.
  # ss.dependency "gRPC-ProtoRPC"
  ss.dependency "#{s.name}/Messages"
  ss.dependency "SwiftGRPC"
  ss.dependency "GRPCError"
  end

  # s.pod_target_xcconfig = {
  # # This is needed by all pods that depend on Protobuf:
  # 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1',
  # # This is needed by all pods that depend on gRPC-RxLibrary:
  # 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES',
  # }

end
复制代码

到这里已经可以使用了,对于剩余的一些需要修改代码以及 compiler 的问题都是一此小问题了。


以上所述就是小编给大家介绍的《iOS的 gRPC 之路》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

HTML5与CSS3基础教程(第7版)

HTML5与CSS3基础教程(第7版)

[美] Elizabeth Castro、[美] Bruce Hyslop / 望以文 / 人民邮电出版社 / 2013-1 / 59.00元

代表下一代网页编写技术的HTML5,为网页提供布局和格式的CSS3,这两者构成了Web开发的基石,也是Web程序员和设计师必须熟练掌握的最基本技能。 本书是风靡全球的HTML和CSS最佳入门教程的最新版,上一版单单英文版的销量就超过100万册,被翻译为十多种语言,并长期雄踞亚马逊书店计算机图书排行榜榜首。 最新的第7版秉承前一版直观、透彻、全面、循序渐进的讲授特色,仍然采用独特的双栏图......一起来看看 《HTML5与CSS3基础教程(第7版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码