做者: iOS 团队 - 王玎html
##为何要用?ios
##咱们的指望c++
##现实状况git
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); } }];github
咱们的:public class func getHomePageShowArea(success: @escaping ([TRHomePageArea]) -> Void, failure: ((Error) -> Void)? = nil)shell
##怎么办? ###鉴于上述状况,咱们有了如下的方案 经过 NS_REFINED_FOR_SWIFT 这个宏所标记的函数、方法和变量在 Obj-C 代码中能够正常使用,但当它们桥接到 Swift 的时候,名称前面就会加上“__”。经过在 Obj-C 代码中使用这个宏,咱们就能够在 Swift 代码中使用相同的名称来提供一个更便于使用的 API ,就像下面这样:swift
可是,对于每个生成的文件,极大的可能都会有一个这种转换文件与之对应。这会形成运行时的体积增大,工程体积增大。api
###如今的方案swift-grpcruby
现有的资源: grpc-swift: github.com/grpc/grpc-s… swift-protobuf: github.com/apple/swift…bash
问题:
####初始的想法
因为 grpc-objc 是肯定可使用的,那么是否是可使用 swift 的代码来彻底替代生成的 oc代码,初步看来好像是可行的:
responseClass:[Template class]
接下来直接改 swift-protobuf 的编译器,让它生成 class 是不 是就能够了?通过实践的证实,它远远不是改一下编译器那么简单的事情,在 swift-protobuf runtime library 中还须要咱们提供一个对 class 的序列化,看了下它们实现,
####想法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> 这样以后,编译经过。
完成了这两个库的安装后,终于能够进入正题了。建立
因为这三个工具是通过代码修改生成的,因此咱们必须修改 podspec 文件来指定使用这三个工具,因为没有保存那个版本,因此就不展现了,有须要的能够联系我。
大功告成!!2333333333
再测试一下,生成一个带有引用文件,好比这个
pod install 以后果断报错啊,
经过一番查找尝试,原来还要指定搜索参数。而后就有了如下的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 的问题都是一此小问题了。