【規範建議】服務端介面返回欄位型別與iOS端的解析
一、本文件的寫作目的
App需要跟產品、UI、後臺、伺服器、測試打交道,app的產出是其他端人員產出的綜合體現。與其他端人員溝通就像是開發寫介面,也就是面向介面程式設計的思想。
本文件講解針對的是服務端返回資料時使用的欄位資料型別如何選擇、iOS端將JSON資料轉模型的時候用什麼型別來定義對應的屬性。
二、本文件的使用範圍
首先介紹下在本文件中使用的技術領域。
1、服務端使用的是C#語言
2、Api介面文件自動生成
3、採用的是JSON資料傳輸格式
4、iOS使用的是Objective-C語言舉例
上面提到的技術範圍並不影響到本文件的推廣。首先,在專案內部嚴格執行。後續可以在公司其他專案組中結合實際情況完成落地。
三、正文
伺服器返回的型別 | 使用領域 | iOS端模型中屬性型別 | NSLog輸出格式 |
integer | 表示整型資料 | NSInteger | %ld |
decimal number | 資料相關的最好使用浮點型 | CGFloat | %f、%0.2f |
boolean | 判斷是否的資料 | BOOL | %ld |
string | 文字資訊 | NSString | %@ |
date | 時間資訊(要求伺服器的dateFormat統一) | NSDate | %@ |
Enum | 列舉 | Enum | %ld |
物件 | 裡面的內容多處使用,封裝成物件 | Model類 | %@ |
Collection of string | 基本資料型別的集合 | NSArray<NSString *> | %@ |
Collection of 物件 | 物件型別的集合 | NSArray<類名 *> | %@ |
簡單的表格羅列出來的資訊總是意猶未盡,有幾個重要的資訊說明如下:
(1)使用NSInteger、CGFloat、BOOL,而不要使用int、float、double、bool甚至是NSNumber。
解釋:
首先,不使用int而使用NSInteger等是屬於語言特性邏輯,NSInterger對int多了處理,比如會結合執行平臺使用int_32\int_64。
然後不使用NSNumber的原因是,NSNmuber採用的是類簇裝箱拆箱,NSNumber只是中間量,表述不清楚。JSON轉字典再轉模型,OC語言中字典中的的元素必須是物件型別,因此使用NSNumber放置在字典中,但是在字典轉模型的時候不還原它的裝箱前的本來面目,對使用該模型的開發人員不友好。
(2)關於date型別的說明。
解釋:
date型別通過JSON資料傳輸時是字串型別。它的由來是,首先伺服器用date型別表示時間類,時間類中包含著很多的資訊,需要通過dateFormat時間表述格式轉換成字串型別返回。JSON轉換成字典的時候,date在字典中是NSString型別,iOS端需要還原它的本來面目。但是在轉換成NSDate的使用需要知道之前date轉string的時候使用的dateFormat,因此關於dateFormat需要要求服務端開發人員統一規範(比如我們公司使用的是"YYYY-MM-dd HH:mm:ss")。
在開發過程中容易在date這塊出現模糊出現動搖,比如產品上的要求是將兩個時間合併在一起顯示(2018年10月10日 6:00 - 18:00),這種情境下服務端是將兩個date欄位返回呢、還是將顯示的內容拼接好之後使用string欄位返回呢?其實,原則很簡單:伺服器返回資料到客戶端的目的無非就是兩個,第一個目的就是為了顯示,另一個目的就是為了客戶端做邏輯判斷。在這裡,如果客戶端不需要使用“開始時間”或者“結束時間”做業務處理,那麼就讓服務端做好拼裝用string返回,客戶端拿到這個資料之間顯示。相反,如果客戶端需要使用“開始時間”或者“結束時間”做邏輯判斷,那麼就用兩個date欄位返回,拼接顯示的事情交給客戶端處理。
關於時間資訊採用什麼資料型別,另一種方案就是全部使用時間戳,採用integer型別返回。兩種方案都可以,統一好就行。
(3)關於Enum型別的說明。
解釋:enum型別本質上就是int型別。為了體現列舉欄位的列舉性質,iOS端需要在模型上建立一個同樣的列舉型別。這一點無需置疑,但是在實際的專案開發中依然會出現一些搖擺不定的方案。以下舉例一起搖擺不定的例子,後面會給出一些建議方案:
比如,訂單狀態這個欄位。
之前介面中使用的是列舉欄位,iOS端通過enum定義列舉型別。
後面產品上的設計需要將訂單狀態對應的文字(比如1-“未支付”、2-“已支付”等)顯示在介面中。iOS採用的是本地硬編碼的方式,將列舉值與文字對應起來。
但是當產品上的設計需要將“已支付”改成“完成支付”顯示的時候,硬編碼肯定是不行的。所以介面中增加一個訂單狀態的string型別用來顯示其對應的文字內容。
再後來,服務端同學覺得兩個欄位可以合併為一個物件模型(keyValueModel類,屬性key:int,屬性value:string),至於列舉的種類,在欄位的說明區域顯示。
使用keyValueModel類一段時間後發現,列舉的範圍增加後,服務端同學容易忘記在欄位的說明區域編輯了,或者是列舉值十多種之後,顯示不下(顯示不雅觀)。
其實這個問題很好解決,還是使用上面提到的原則。使用兩個欄位,列舉欄位用來供客戶端的同學做邏輯判斷、string欄位用來供客戶端的同學做介面展示。
四、總結
根據“伺服器返回資料到客戶端的目的無非就是兩個,第一個目的就是為了顯示,另一個目的就是為了客戶端做邏輯判斷”的原則,結合產品的設計需求,作用統一化的處理。