Protocol Buffers 在 iOS 中的使用
翻譯自:Introduction to Protocol Buffers on iOS
對(duì)大多數(shù)的應(yīng)用來(lái)說(shuō),后臺(tái)服務(wù)、傳輸和存儲(chǔ)數(shù)據(jù)都是個(gè)重要的模塊。開(kāi)發(fā)者在給一個(gè) web service 寫(xiě)接口時(shí),通常使用 JSON 或者 XML 來(lái)發(fā)送和接收數(shù)據(jù),然后根據(jù)這些數(shù)據(jù)生成結(jié)構(gòu)并解析。
盡管有大量的 API 和框架幫助我們序列化和反序列化,來(lái)支持一些后臺(tái)接口開(kāi)發(fā)的日常工作,比如說(shuō)更新代碼或者解析器來(lái)支持后臺(tái)的模型變化。
但是如果你真的想提升你的新項(xiàng)目的健壯性的話 ,考慮下用?protocol buffers,它是由 Google 開(kāi)發(fā)用來(lái)序列化數(shù)據(jù)結(jié)構(gòu)的一種跨語(yǔ)言的方法。在很多情況下,它比傳統(tǒng)的 JSON 和 XML 更加靈活有效。其中一個(gè)關(guān)鍵的特點(diǎn)就是,你只需要在其支持的任何語(yǔ)言和編譯器下,定義一次數(shù)據(jù)結(jié)構(gòu)——包括 Swift! 創(chuàng)建的類文件就可以很輕松的讀寫(xiě)成對(duì)象。
在這篇教程中,會(huì)使用一個(gè) Python 服務(wù)端與一個(gè) iOS 程序交互。你會(huì)學(xué)到 protocol buffers 是如何工作,如何配置環(huán)境,最后怎樣使用 protocol buffers 傳輸數(shù)據(jù)。
怎么,還是不相信 protocol buffers 就是你所需要的東西?接著往下讀吧。
注意:這篇教程是基于你已經(jīng)有了一定的 iOS 和 Swift 經(jīng)驗(yàn),同時(shí)有一定的基本的服務(wù)端和 terminal 基礎(chǔ)。 同時(shí),確保你使用的是蘋(píng)果的 Xcode 8.2或以后的版本.
##準(zhǔn)備開(kāi)始 RWCards這個(gè)APP可以用來(lái)查看你的會(huì)議門(mén)票和演講者名單。下載Starter Project并打開(kāi)根目錄Starter。先熟悉一下這下面這三部分: #####The Client 在?Starter/RWCards下,打開(kāi)?RWCards.xcworkspace,我們來(lái)看看這幾個(gè)主要的文件:
- SpeakersListViewController.swift?管理了一個(gè)用來(lái)展示演講者名單的table view。這個(gè)控制器現(xiàn)在還只是個(gè)模板因?yàn)槟氵€沒(méi)有為其創(chuàng)建模型。
- SpeakersViewModel.swift?相當(dāng)于 SpeakersListViewController 的數(shù)據(jù)源,它會(huì)包含有演講者的名單數(shù)據(jù)。
- CardViewController.swift?用來(lái)展示參會(huì)者的名片和他的社交信息.
- RWService.swift 管理客戶端和后端的交互。你可能會(huì)用到 Alamofire 來(lái)發(fā)起服務(wù)請(qǐng)求。
- Main.storyboard?整個(gè) APP 的 storyboard.
整個(gè)工程使用?CocoaPods?來(lái)拉取這兩個(gè)框架:
- Swift Protobuf?支持在 Xcode 中使用 Protocol Buffers.
- Alamofire?一個(gè) HTTP 網(wǎng)絡(luò)庫(kù),你會(huì)用到它來(lái)請(qǐng)求服務(wù)器。
注意:這篇教程中你會(huì)用到 Swift Protobuf 0.9.24 和 Google’s Protoc Compiler 3.1.0. 它們已經(jīng)打包在項(xiàng)目里了,所以你不需要再做別的。
Protocol Buffers 是如何工作的?
開(kāi)始使用 protocol buffers 前,首先要定義一個(gè) .proto 文件。在這個(gè)文件中指定了你的數(shù)據(jù)結(jié)構(gòu)信息。下面是一個(gè) .proto 文件的示例:
syntax = "proto3";message Contact {enum ContactType {SPEAKER = 0;ATTENDANT = 1;VOLUNTEER = 2;}string first_name = 1;string last_name = 2;string twitter_name = 3;string email = 4;string github_link = 5;ContactType type = 6;string imageName = 7; }; 復(fù)制代碼這個(gè)文件里定義了一個(gè) Contact 的 message 和它的相關(guān)屬性。
.proto 文件定義好了后,你只需要把這個(gè)文件交給 protocol buffer 的編譯器,編譯器會(huì)用你選擇的語(yǔ)言創(chuàng)建好一個(gè)數(shù)據(jù)類(Swift 中的 結(jié)構(gòu))。你可以直接在項(xiàng)目中使用這個(gè)類/結(jié)構(gòu),非常簡(jiǎn)單!
編譯器會(huì)將 .proto 中的 message 轉(zhuǎn)換成事先選擇的語(yǔ)言,并生成模型對(duì)象的源文件。后面會(huì)提到定義**.proto**信息的更多細(xì)節(jié)。 另外在考慮 protocol buffers 之前,你應(yīng)該考慮它是不是你項(xiàng)目的最佳方案。優(yōu)勢(shì)
JSON 和 XML 可能是目前開(kāi)發(fā)者們用來(lái)存儲(chǔ)和傳輸數(shù)據(jù)的標(biāo)準(zhǔn)方案,而 protocol buffers 與之相比有以下優(yōu)勢(shì):
- 快速且小巧:按照 Google 所描述的,protocol buffers 的體積要小3-10倍,速度比XML要快20-100倍。可以在這篇文章?,它的作者是 Damien Bod,文中比較了一些主流文本格式的讀寫(xiě)速度。
- 類型安全:Protocol buffers 像 Swift 一樣是類型安全的,使用 protocol buffers 時(shí) 你需要指定每一個(gè)屬性的類型。
- 自動(dòng)反序列化:你不需要再去編寫(xiě)任何的解析代碼,只需要更新 .proto 文件就行了。 file and regenerate the data access classes.
- 分享就是關(guān)心:因?yàn)橹С侄喾N語(yǔ)言,因此可以在不同的平臺(tái)中共享數(shù)據(jù)模型,這意味著跨平臺(tái)的工作會(huì)更輕松。
局限性
Protocol buffers 雖然有著諸多優(yōu)勢(shì),但是它也不是萬(wàn)能的:
- 時(shí)間成本:在老項(xiàng)目中去使用 protocol buffers 可能會(huì)不太高效,因?yàn)樾枰D(zhuǎn)換成本。同時(shí),項(xiàng)目成員還需要去學(xué)習(xí)一種新的語(yǔ)法。
- 可讀性:XML 和 JSON 的描述性更好,并且易于閱讀。Protocol buffers 的原數(shù)據(jù)無(wú)法閱讀,并且在沒(méi)有 .proto 文件的情況下沒(méi)辦法解析。
- 僅僅是不適合而已:當(dāng)你想要使用類似于XSLT這樣的樣式表時(shí),XML是最好的選擇。所以 protocol buffers 并不總是最佳工具。
- 不支持:編譯器可能不支持你正在進(jìn)行中的項(xiàng)目所使用的語(yǔ)言和平臺(tái)。
盡管并不是適合于所有的情況,但 protocol buffers 確確實(shí)實(shí)有著很多的優(yōu)勢(shì)。 把程序運(yùn)行起來(lái)試試看吧。
不幸的是你現(xiàn)在還看不到任何信息,因?yàn)閿?shù)據(jù)源還沒(méi)有初始化。你要做的是請(qǐng)求服務(wù)端并且將演講者和參會(huì)者數(shù)據(jù)填充到頁(yè)面上。首先,你會(huì)看到項(xiàng)目中提供的:Protocol Buffer 模板
Head back to Finder and look inside?Starter/ProtoSchema. You’ll see the following files: 打開(kāi) Starter/ProtoSchema 目錄,你會(huì)看到這些文件:
- contact.proto?用 protocol buffer 的語(yǔ)法定義了一個(gè) contact 的結(jié)構(gòu)。之后會(huì)更詳細(xì)地說(shuō)明這個(gè)。
- protoScript.sh?這個(gè) bash 腳本使用 protocol buffer 的編譯器讀取 contact.proto 分別生成了 Swift 和 Python 的數(shù)據(jù)模型。
服務(wù)端
Starter/Server 目錄下包括:
-
RWServer.py 是放在Flask上的一個(gè) Python 服務(wù)。包含兩個(gè) GET 請(qǐng)求:
- /currentUser 獲取當(dāng)前參會(huì)者的信息。
- /speakers 獲取演講者列表。
-
RWDict.py?包含了 RWServer 將要讀取的演講者列表數(shù)據(jù).
現(xiàn)在是時(shí)候配置環(huán)境來(lái)運(yùn)行 protocol buffers 了。在下面的章節(jié)中,你會(huì)創(chuàng)建好運(yùn)行 Google 的 protocol buffer編譯器環(huán)境,Swift 的 Protobuf 插件,并安裝 Flask 來(lái)運(yùn)行你的 Python 服務(wù)。
環(huán)境配置
在使用 protocol buffers 之前需要安裝許多的工具和庫(kù)。starter 項(xiàng)目中包含了一個(gè)名為 protoInstallation.sh 的腳本幫你搞定了這些。它會(huì)在安裝之前檢查是否已經(jīng)安裝過(guò)這些庫(kù)。 這個(gè)腳本需要花一點(diǎn)時(shí)間來(lái)安裝,尤其是安裝 Google 的 protocol buffer 庫(kù)。打開(kāi)你的終端,cd 命令進(jìn)入到 Starter 目錄執(zhí)行下面這個(gè)命令:
$ ./protoInstallation.sh 復(fù)制代碼注意:執(zhí)行的過(guò)程中你可能會(huì)被要求輸入管理員密碼。
腳本執(zhí)行完成后,再運(yùn)行一次以確保的到以下輸出結(jié)果:
如果你看到這些,那表示腳本已經(jīng)執(zhí)行完畢。如果腳本執(zhí)行失敗了,那檢查下你是不是輸入了錯(cuò)誤的管理員密碼。并重新運(yùn)行腳本;它不會(huì)重新安裝那些已經(jīng)成功的庫(kù)。 這個(gè)腳本做了這些事:
注意:你可以用編輯器打開(kāi) protoInstallation.sh 文件來(lái)了解這個(gè)腳本是如何工作的。這需要一定的 bash 基礎(chǔ)。
好了,現(xiàn)在你已經(jīng)做好了使用 protocol buffers 的所有準(zhǔn)備工作。
定義一個(gè) .proto 文件
.proto 文件定義了 protocol buffer 描述你的數(shù)據(jù)結(jié)構(gòu)的 message。把這個(gè)文件中的內(nèi)容傳遞給 protocol buffer 編譯器后,編譯器會(huì)生成你的數(shù)據(jù)結(jié)構(gòu)。
注意:在這篇教程中,你將使用 proto3 來(lái)定義 message,這是 protocol buffer 語(yǔ)言的最新版本??梢栽L問(wèn)Google’s guidelines以獲取更多的 proto3 的信息。
用你最習(xí)慣的編輯器打開(kāi) ProtoSchema/contact.proto ,這里已經(jīng)定義好了演講者的 message:
syntax = "proto3";message Contact { // 1enum ContactType { // 2SPEAKER = 0;ATTENDANT = 1;VOLUNTEER = 2;}string first_name = 1; //3string last_name = 2;string twitter_name = 3;string email = 4;string github_link = 5;ContactType type = 6;string imageName = 7; };message Speakers { // 4repeated Contact contacts = 1; }; 復(fù)制代碼我們來(lái)看一下這里面包含了哪些內(nèi)容:
The?Contact model describes a person’s contact information. This will be displayed on their badges in the app.
##生成 Swift 結(jié)構(gòu) 把 contact.proto 傳遞給 protoc 程序,proto 文件中的 message 將會(huì)被轉(zhuǎn)化生成 Swift 的結(jié)構(gòu)。這些結(jié)構(gòu)會(huì)遵循 ProtobufMessage.protoc 并提供 Swift 中構(gòu)造、方法來(lái)序列化和反序列化數(shù)據(jù)的途徑。
注意:想了解更多關(guān)于 Swift 的 protobuf API, 訪問(wèn)蘋(píng)果的?Protobuf API documentation.
在終端中,進(jìn)入** Starter/ProtoSchema **目錄,用編輯器打開(kāi) protoScript.sh,你會(huì)看到:
echo 'Running ProtoBuf Compiler to convert .proto schema to Swift' protoc --swift_out=. contact.proto // 1 echo 'Running Protobuf Compiler to convert .proto schema to Python' protoc -I=. --python_out=. ./contact.proto // 2 復(fù)制代碼這個(gè)腳本對(duì) contact.proto 文件執(zhí)行了兩次 protoc 命令,分別創(chuàng)建了 Swift 和 Python 的源文件。 回到終端,執(zhí)行下面的命令:
$ ./protoScript.sh 復(fù)制代碼你會(huì)看到以下輸出結(jié)果:
Running ProtoBuf Compiler to convert .proto schema to Swift protoc-gen-swift: Generating Swift for contact.proto Running Protobuf Compiler to convert .proto schema to Python 復(fù)制代碼你已經(jīng)創(chuàng)建好了 Swift 和 Python 的源文件。 在 ** ProtoSchema** 目錄下,你會(huì)看到一個(gè) Swift 和一個(gè) Python 文件。同時(shí)分別還有一個(gè)對(duì)應(yīng)的 .pb.swift 和 .pb.py. pb 前綴表示這是 protocol buffer 生成的類。
把 contact.pb.swift 拖到 Xcode 的 project navigator 下的 Protocol Buffer Objects 組. 勾上“Copy items if needed”選項(xiàng)。同時(shí)將 contact_pb2.py 拷貝到 Starter/Server 目錄。 看一眼 ** contact.pb.swift** 和 contact_pb2.py中的內(nèi)容,看看 proto message 是如何轉(zhuǎn)換成目標(biāo)語(yǔ)言的。 現(xiàn)在你已經(jīng)有了生成好的模型對(duì)象了,可以開(kāi)始集成了! ##運(yùn)行本地服務(wù)器 示例代碼中包含了一個(gè) Python 服務(wù)。這個(gè)服務(wù)提供了兩個(gè) GET 請(qǐng)求:一個(gè)用來(lái)獲取參會(huì)者的名牌信息,另一個(gè)用來(lái)列出演講者。 這個(gè)教程不會(huì)深入講解服務(wù)端的代碼。盡管如此,你需要了解到它用到了由 protocol buffer 編譯器生成的 contact_pb2.py 模型文件。如果你感興趣,可以看一看 RWServer.py 中的代碼,不看也無(wú)妨(手動(dòng)滑稽)。 打開(kāi)終端并 cd 至 Starter/Server 目錄,運(yùn)行下面的命令:
$ python RWServer.py復(fù)制代碼運(yùn)行結(jié)果如下:
測(cè)試 GET 請(qǐng)求
通過(guò)在瀏覽器中發(fā)起 HTTP 請(qǐng)求,你可以看到 protocol buffer 的原數(shù)據(jù)。 在瀏覽器中打開(kāi) http://127.0.0.1:5000/currentUser 你會(huì)看到:
再試試演講者的接口,http://127.0.0.1:5000/speakers:
注意:測(cè)試 RWCards app的過(guò)程中你可以退出、中止和重啟本地服務(wù)以便調(diào)試。
現(xiàn)在你已經(jīng)運(yùn)行了本地服務(wù)器,它使用的是由 proto 文件生成的模型,是不是很cooool?
發(fā)起服務(wù)請(qǐng)求
現(xiàn)在你已經(jīng)把本地服務(wù)器跑起來(lái)了,是時(shí)候在 app 中發(fā)起服務(wù)請(qǐng)求了。**RWService.swift **文件中將 RWService 類替換成下面的代碼:
class RWService {static let shared = RWService() // 1let url = "http://127.0.0.1:5000"private init() { }func getCurrentUser(_ completion: @escaping (Contact?) -> ()) { // 2let path = "/currentUser"Alamofire.request("\(url)\(path)").responseData { response inif let data = response.result.value { // 3let contact = try? Contact(protobuf: data) // 4completion(contact)}completion(nil)}} } 復(fù)制代碼這個(gè)類將用來(lái)與你的 Python 服務(wù)器進(jìn)行交互。你已經(jīng)實(shí)現(xiàn)了獲取當(dāng)前用戶的請(qǐng)求:
解碼數(shù)據(jù)只需要把 protocol buffer 的數(shù)據(jù)傳遞給對(duì)象的構(gòu)造器即可,不需要其他的解析。 Swift 的 protocol buffer 庫(kù)幫你處理了所有的事情。 現(xiàn)在請(qǐng)求已經(jīng)完成,可以展示數(shù)據(jù)了。
集成參會(huì)者的名片
打開(kāi) CardViewController.swift 文件并在 viewWillAppear(_:) 之后添加下面這些代碼:
func fetchCurrentUser() { // 1RWService.shared.getCurrentUser { contact inif let contact = contact {self.configure(contact)}} }func configure(_ contact: Contact) { // 2self.attendeeNameLabel.attributedText = NSAttributedString.attributedString(for: contact.firstName, and: contact.lastName)self.twitterLabel.text = contact.twitterNameself.emailLabel.text = contact.emailself.githubLabel.text = contact.githubLinkself.profileImageView.image = UIImage(named: contact.imageName) } 復(fù)制代碼這些方法會(huì)幫你取得服務(wù)端傳過(guò)來(lái)的數(shù)據(jù),并用來(lái)配置名片:
用起來(lái)很簡(jiǎn)單,但是還需要拿到一個(gè) ContactType 枚舉用來(lái)區(qū)分參會(huì)者的類型。
自定義 Protocol Buffer 對(duì)象
你需要添加一個(gè)方法來(lái)把枚舉類型轉(zhuǎn)換成 string, 這樣名片頁(yè)面才能顯示 SPEAKER 而不是一個(gè)數(shù)字0. 但是這有個(gè)問(wèn)題,如果不重新生成 .proto 文件來(lái)更新 message,怎樣才能往模型里添加新功能呢?
Swift extensions 可以搞定這個(gè),它可以讓你添加一些信息到類中而不需要改變類本身的代碼。 創(chuàng)建一個(gè)名為 contact+extension.swift 的文件,并添加到 Protocol Buffer Objects 目錄。添加以下代碼: extension Contact {func contactTypeToString() -> String {switch type {case .speaker:return "SPEAKER"case .attendant:return "ATTENDEE"case .volunteer:return "VOLUNTEER"default:return "UNKNOWN"}} } 復(fù)制代碼contactTypeToString() 方法將 ContactType 映射成了一個(gè)對(duì)應(yīng)的顯示用的字符串。 打開(kāi) CardViewController.swift 并添加下面的代碼到 configure(_:):
self.attendeeTypeLabel.text = contact.contactTypeToString()復(fù)制代碼將代表contact type的字符串傳遞給了 * attendeeTypeLabel*。 最后在 viewWillAppear(_:) 中,applyBusinessCardAppearance() 之后添加下面代碼:
if isCurrentUser {fetchCurrentUser() } else {// TODO: handle speaker } 復(fù)制代碼- isCurrentUser* 已經(jīng)被硬編碼成 true, 當(dāng)被設(shè)置為演講者時(shí)這個(gè)值會(huì)被修改。*fetchCurrentUser() * 方法在默認(rèn)情況下會(huì)被調(diào)用,獲取名片信息并將其填充到名片上。 運(yùn)行程序來(lái)看看參會(huì)者的名片頁(yè)面:
集成演講者列表
My Badge 選項(xiàng)卡完成后,我們來(lái)看看 Speakers 選項(xiàng)卡。 打開(kāi) RWService.swift 并添加下面的代碼:
func getSpeakers(_ completion: @escaping (Speakers?) -> ()) { // 1let path = "/speakers"Alamofire.request("\(url)\(path)").responseData { response inif let data = response.result.value { // 2let speakers = try? Speakers(protobuf: data) // 3completion(speakers)}}completion(nil) } 復(fù)制代碼看上去很熟悉是吧,它和 getCurrentUser(_:) 類似,不過(guò)他獲取的是 Speakers 對(duì)象,包含了一個(gè) contact 的數(shù)組,用于表示回憶的演講者。 打開(kāi) SpeakersViewModel.swift 并將代碼替換為:
class SpeakersViewModel {var speakers: Speakers!var selectedSpeaker: Contact?init(speakers: Speakers) {self.speakers = speakers}func numberOfRows() -> Int {return speakers.contacts.count}func numberOfSections() -> Int {return 1}func getSpeaker(for indexPath: IndexPath) -> Contact {return speakers.contacts[indexPath.item]}func selectSpeaker(for indexPath: IndexPath) {selectedSpeaker = getSpeaker(for: indexPath)} } 復(fù)制代碼SpeakersListViewController 顯示了一個(gè)參會(huì)者的列表,SpeakersViewModel中包含了這些數(shù)據(jù):從 /speakers 接口中獲取的contact對(duì)象組成的數(shù)組。 SpeakersListViewController將在每一行中顯示一個(gè)speaker。 viewmodel創(chuàng)建好了之后,就該配置cell了。打開(kāi) SpeakerCell.swift,添加下面的代碼到 SpeakerCell:
func configure(with contact: Contact) {profileImageView.image = UIImage(named: contact.imageName)nameLabel.attributedText = NSAttributedString.attributedString(for: contact.firstName, and: contact.lastName) } 復(fù)制代碼傳入了一個(gè)contact對(duì)象并且通過(guò)其屬性來(lái)配置cell的 image 和 label。這個(gè)cell會(huì)顯示演講者的照片,和他的名字。 接下來(lái),打開(kāi) SpeakersListViewController.swift 并添加下面的代碼到 *viewWillAppear(_:)*中:
RWService.shared.getSpeakers { [unowned self] speakers inif let speakers = speakers {self.speakersModel = SpeakersViewModel(speakers: speakers)self.tableView.reloadData()} } 復(fù)制代碼getSpeakers(_:)發(fā)起了一個(gè)請(qǐng)求去獲取演講者列表的數(shù)據(jù),創(chuàng)建了一個(gè) * SpeakersViewModel 的對(duì)象,并返回 speakers。 tableview 接下來(lái)會(huì)更新這些獲取到的數(shù)據(jù)。 你需要給 tableview 的每一行指定一個(gè)speaker用于顯示。替換tableView(_:cellForRowAt:)*的代碼:
let cell = tableView.dequeueReusableCell(withIdentifier: "SpeakerCell", for: indexPath) as! SpeakerCell if let speaker = speakersModel?.getSpeaker(for: indexPath) {cell.configure(with: speaker) } return cell 復(fù)制代碼getSpeaker(for:) 根據(jù)當(dāng)前列表的 indexPath返回 speaker數(shù)據(jù),通過(guò)cell的*configure(with:)*配置cell。 當(dāng)點(diǎn)擊列表中的一個(gè)cell時(shí),你需要跳轉(zhuǎn)到 CardViewController 展示選擇的演講者信息,打開(kāi) CardViewController.swift 并在類中添加這些屬性:
var speaker: Contact?復(fù)制代碼后面會(huì)用到這個(gè)屬性用來(lái)傳遞選擇的演講者。將*// TODO: handle speaker*替換為:
if let speaker = speaker {configure(speaker) } 復(fù)制代碼這個(gè)判斷用來(lái)確定 speaker 是否已經(jīng)填充過(guò)了,如果是,調(diào)用 configure(),在名片上更新演講者的信息。 回到 SpeakersListViewController.swift 傳遞選擇的 speaker。在 *tableView(_:didSelectRowAt:)*中, performSegue(withIdentifier:sender:) 上方添加:
speakersModel?.selectSpeaker(for: indexPath)復(fù)制代碼將 speakersModel 中的對(duì)應(yīng) speaker 標(biāo)記為選中。 接下來(lái),在*prepare(for:sender:)*的 vc.isCurrentUser = false: 之后添加下面的代碼:
vc.speaker = speakersModel?.selectedSpeaker復(fù)制代碼這里講 selectedSpeaker 傳遞給了 * CardViewController* 來(lái)顯示。 確保你的本地服務(wù)還在運(yùn)行當(dāng)中,build & run Xcode。你會(huì)看到 app 已經(jīng)集成了用戶名片,同時(shí)顯示了演講者的信息。
你已經(jīng)成功地用Swift的客戶端和Python的服務(wù)端,構(gòu)建好了一個(gè)應(yīng)用程序??蛻舳撕头?wù)端同時(shí)使用了由 proto 文件創(chuàng)建的模型。如果你需要修改模型,只需要簡(jiǎn)單地運(yùn)行編譯器并重新生成,就能立刻得到兩端的模型文件!總結(jié)
你可以從?這里下載到完成的工程。 在這篇教程中,你已經(jīng)學(xué)習(xí)到了 protocol buffer 的基本特征, 怎樣定義一個(gè) .proto 文件并通過(guò)編譯器生成 Swift 文件。還學(xué)習(xí)了如何使用Flask 創(chuàng)建一個(gè)簡(jiǎn)單的本地服務(wù)器,并使用這個(gè)服務(wù)發(fā)送 protocol buffer 的二進(jìn)制數(shù)據(jù)給客戶端,以及如何輕松地去反序列化數(shù)據(jù)。 protocol buffers 還有更多的特性,比如說(shuō)在 message 中定義映射和處理向后兼容。如果你對(duì)這些感興趣,可以查看 Google 的文檔。
最后值得一提的是,Remote Procedure Calls這個(gè)項(xiàng)目使用了 protocol buffers 并且看起來(lái)非常不錯(cuò),訪問(wèn)GRPC了解更多吧。
總結(jié)
以上是生活随笔為你收集整理的Protocol Buffers 在 iOS 中的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: micropython esp8266+
- 下一篇: ajaxSetup