做者: 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 文件來進行集成使用了。因爲前面的研究,咱們生成代碼須要的是這三個工具:因爲這三個工具是通過代碼修改生成的,因此咱們必須修改 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 的問題都是一此小問題了。