一勞永逸的解決AFNetworking3.0網路請求問題(面向對象封裝大法,block回調)

来源:http://www.cnblogs.com/beckwang0912/archive/2017/06/20/7052782.html
-Advertisement-
Play Games

AFNetworking在iOS網路請求第三方庫中占據著半壁江山,前段時間將AFNetworking進行了3.0版本的遷移,運用面向對象的設計將代碼進行封裝整合,這篇文章主要為還在尋找AFNetworking集成代碼或者準備3.0遷移的各位童鞋們提供思路,同時自定義了字典模型轉換方法,需要的朋友也可 ...


      AFNetworking在iOS網路請求第三方庫中占據著半壁江山,前段時間將AFNetworking進行了3.0版本的遷移,運用面向對象的設計將代碼進行封裝整合,這篇文章主要為還在尋找AFNetworking集成代碼或者準備3.0遷移的各位童鞋們提供思路,同時自定義了字典模型轉換方法,需要的朋友也可以作為參考,還望各位老司機批評指正!先上代碼框架圖:

1、DB數據訪問層,在AFNetworkingManager中我將AFNetworking的GET/POST/DELETE/PUT方法封裝,提供了以下介面:

 1 /**
 2  *  get方式請求數據
 3  *
 4  *  @param strUrl          api地址
 5  *  @param headers         頭部信息
 6  *  @param params          可變參數信息
 7  *  @param class           返回數據模型類
 8  *  @param block           block結果回調
 9  *  @param blockError      block錯誤回調
10  *  @param blockTimeOut    block超時回調
11  */
12 -(void)getDataFromUrl:(NSString *)strUrl
13               headers:(NSDictionary *)headers
14                params:(NSDictionary *)params
15                 class:(Class)class
16             block:(CompletionLoad)block
17             blockError:(void (^)(JsonCommonResultBase *))blockError
18             blockTimeOut:(TimeOutCompletion)blockTimeOut;
19 
20 /**
21  *  post方式更新數據
22  *
23  *  @param strUrl          api地址
24  *  @param headers         頭部信息
25  *  @param params          可變參數信息
26  *  @param class           返回數據模型類
27  *  @param block           block結果回調
28  *  @param blockError      block錯誤回調
29  *  @param blockTimeOut    block超時回調
30  */
31 - (void)postDataFromUrl:(NSString*)strUrl
32                 headers:(NSDictionary*)headers
33                  params:(NSDictionary*)params
34                   class:(Class)class
35             block:(CompletionLoad)block
36             blockError:(void(^)(JsonCommonResultBase *))blockError
37             blockTimeOut:(TimeOutCompletion)blockTimeOut;
38 
39 /**
40  *  put方式更新數據
41  *
42  *  @param strUrl          api地址
43  *  @param headers         頭部信息
44  *  @param params          可變參數信息
45  *  @param class           返回數據模型類
46  *  @param block           block結果回調
47  *  @param blockError      block錯誤回調
48  *  @param blockTimeOut    block超時回調
49  */
50 - (void)putDataFromUrl:(NSString*)strUrl
51                headers:(NSDictionary*)headers
52                 params:(NSDictionary*)params
53                  class:(Class)class
54             block:(CompletionLoad)block
55             blockError:(void(^)(id))blockError
56             blockTimeOut:(TimeOutCompletion)blockTimeOut;
57 
58 /**
59  *  delete方式刪除數據
60  *
61  *  @param strUrl          api地址
62  *  @param headers         頭部信息
63  *  @param params          可變參數信息
64  *  @param class           返回數據模型類
65  *  @param block           block結果回調
66  *  @param blockError      block錯誤回調
67  *  @param blockTimeOut    block超時回調
68  */
69 - (void)deleteDataFromUrl:(NSString*)strUrl
70                   headers:(NSDictionary*)headers
71                    params:(NSDictionary*)params
72                     class:(Class)class
73             block:(CompletionLoad)block
74             blockError:(void(^)(JsonCommonResultBase *))blockError
75             blockTimeOut:(TimeOutCompletion)blockTimeOut;
76 
77 /**
78  *  post方式更新數據(上傳文件如圖片)
79  *
80  *  @param strUrl          api地址
81  *  @param headers         頭部信息
82  *  @param params          可變參數信息
83  *  @param dataFiles       文件數據
84  *  @param class           返回數據模型類
85  *  @param block           block結果回調
86  *  @param progressBlock   block進度回調
87  *  @param blockError      block錯誤回調
88  *  @param blockTimeOut    block超時回調
89  */
90 - (void)uploadDataFromUrl:(NSString *)strUrl
91                   headers:(NSDictionary *)headers
92                    params:(NSDictionary *)params
93                 dataFiles:(NSArray *)dataFiles
94             progressBlock:(LoadProgress)progressBlock
95                     block:(CompletionLoad)block
96                     class:(Class)class
97             blockError:(void (^)(JsonCommonResultBase *))blockError
98             blockTimeOut:(TimeOutCompletion)blockTimeOut;
AFNetworking封裝

針對AFNetworking底層封裝AFNetworkingManager後,是不是就可以直接在Service調用GET/POST/DELETE/PUT介面訪問數據了呢?理論上是完全可以的,但是我們在實際開發中往往還需要自定義或者個性化一些效果如菊花等待框、陰影效果,提示文案等,所以本人建議在AFNetworkingManager基礎上再包裝一層專門用於Service對接,這樣的好處是Service層完全不必關心AFNetworking的封裝實現和序列化、授權等等問題,這樣也便於後續的維護與版本的升級,好了我們再看看對接Service的ZTHttpManager:

/**
 *  get方式請求數據(內部封裝菊花等待框)
 *
 *  @param strUrl          api地址
 *  @param headers         頭部信息
 *  @param params          可變參數信息
 *  @param parentView      菊花等待框寄托視圖
 *  @param showShadow      是否陰影父視圖
 *  @param blockRtn        block結果回調
 *  @param blockError      block錯誤回調
 *  @param blockTimeOut    block超時回調
 */
- (void)getDataToUrl:(NSString*)strUrl
             headers:(NSDictionary*)headers
              params:(NSDictionary*)params
          parentView:(UIView*)parentView
          showShadow:(BOOL)showShadow
               class:(Class)class
          blockRtn:(void (^)(id ))blockRtn
          blockError:(void(^)(JsonCommonResultBase*))blockError
          blockTimeOut:(TimeOutCompletion)blockTimeOut;

/**
 *  post方式提交數據(內部封裝菊花等待框)
 *
 *  @param strUrl          api地址
 *  @param headers         頭部信息
 *  @param params          可變參數信息
 *  @param parentView      菊花等待框寄托父視圖
 *  @param showShadow      是否陰影父視圖
 *  @param blockRtn        block結果回調
 *  @param blockError      block錯誤回調
 *  @param blockTimeOut    block超時回調
 */
- (void)postDataToUrl:(NSString *)strUrl
              headers:(NSDictionary *)headers
               params:(NSDictionary *)params
           parentView:(UIView *)parentView
           showShadow:(BOOL)showShadow
                class:(Class)class
           blockRtn:(void (^)(id))blockRtn
           blockError:(void(^)(JsonCommonResultBase*))blockError
           blockTimeOut:(TimeOutCompletion)blockTimeOut;

/**
 *  delete方式刪除數據(內部封裝菊花等待框)
 *
 *  @param strUrl          api地址
 *  @param headers         頭部信息
 *  @param params          可變參數信息
 *  @param parentView      菊花等待框寄托視圖
 *  @param showShadow      是否陰影父視圖
 *  @param blockRtn        block結果回調
 *  @param blockError      block錯誤回調
 *  @param blockTimeOut    block超時回調
 */
- (void)deleteDataToUrl:(NSString*)strUrl
                headers:(NSDictionary*)headers
                 params:(NSDictionary*)params
             parentView:(UIView*)parentView
             showShadow:(BOOL)showShadow
                  class:(Class)class
             blockRtn:(void (^)(id ))blockRtn
             blockError:(void(^)(JsonCommonResultBase*))blockError
             blockTimeOut:(TimeOutCompletion)blockTimeOut;


/**
 *  put方式提交數據(內部封裝菊花等待框)
 *
 *  @param strUrl          api地址
 *  @param headers         頭部信息
 *  @param params          可變參數信息
 *  @param parentView      菊花等待框寄托視圖
 *  @param showShadow      是否陰影父視圖
 *  @param blockRtn        block結果回調
 *  @param blockError      block錯誤回調
 *  @param blockTimeOut    block超時回調
 */
- (void)putDataToUrl:(NSString*)strUrl
             headers:(NSDictionary*)headers
              params:(NSDictionary*)params
          parentView:(UIView*)parentView
          showShadow:(BOOL)showShadow
               class:(Class)class
          blockRtn:(void (^)(id))blockRtn
          blockError:(void(^)(JsonCommonResultBase*))blockError
          blockTimeOut:(TimeOutCompletion)blockTimeOut;

/**
 *  post方式上傳文件
 *  @param strUrl          api地址
 *  @param parentView      菊花等待框寄托視圖
 *  @param showShadow      是否陰影父視圖
 *  @param blockRtn        block結果回調
 *  @param blockError      block錯誤回調
 *  @param blockTimeOut    block超時回調
 */
- (void)uploadImgFromUrl:(NSString*)strUrl
               fileItems:(NSArray*)fileItems
              parentView:(UIView*)parentView
              showShadow:(BOOL)showShadow
                 headers:(NSDictionary *)headers
                  params:(NSDictionary *)params
                   class:(Class)class
            blockProgress:(void (^)(NSString *))blockProgress
            blockRtn:(void (^)(id))blockRtn
            blockError:(void(^)(JsonCommonResultBase*))blockError
            blockTimeOut:(TimeOutCompletion)blockTimeOut;
ZTHttpManager封裝

好了,在這裡完成了DB層的代碼,訪問API就毫無壓力了!

2、模型基類JsonCommonResultBase/SerializationBaseModel

在這裡我要說明一點,這裡的模型基類是按照我們公司後臺返回的API格式自定義,不一定適合每個人,但是可以作為各位的參考,具體的API返回數據結構為:

{
    page =     {
        hasMore = 0;
        totalRows = 1;
    };
    result =     (
                {
            annexInfoStatus = Pending;
            bsBeginTime = "2017-03-16 00:00:00";
            bsEndTime = "2018-03-15 23:59:59";
            bzBeginTime = "2017-03-16 00:00:00";
            bzEndTime = "2018-03-15 23:59:59";
            canRenewal = 0;
            company =             {
                code = alltrust;
                id = 16;
            };
            totalPremiums = "9632.09";
            totalPremiumsText = "\U00a59,632.09";
            verifyStatus = Verified;
        }
    );
    status = 200;
}
API返回200數據格式

針對上述的數據格式,自定義的模型基類如下(BTW這裡多層級的數據轉化也是毫無壓力的,完全OK):

@interface SerializationBaseModel : NSObject<NSCopying>

// 獲取列表字典
- (NSDictionary *)objectClassInArray;

@end


@implementation SerializationBaseModel

- (id)copyWithZone:(NSZone *)zone{
    return (id)self;
}

// 獲取列表字典 (具體result實現在子類中)
- (NSDictionary *)objectClassInArray{
    return nil;
}

@end
序列化model基類 需要繼承NSCopying
#pragma mark - 分頁數據模型
@interface ApiPage : SerializationBaseModel

/**
 *  總行數
 */
@property (nonatomic,assign) NSInteger    totalRows;

/**
 *  是否還有數據
 */
@property (nonatomic,assign) BOOL         hasMore;

@end

#pragma mark - Json數據模型
@interface JsonCommonResultBase : SerializationBaseModel

/**
 *  錯誤編碼
 */
@property (nonatomic,copy)  NSString  *errCode;

/**
 *  錯誤消息
 */
@property (nonatomic,copy)  NSString  *errMsg;

/**
 *  請求狀態
 */
@property (nonatomic,assign)  NSInteger status;

/**
 *  分頁信息
 */
@property (nonatomic,strong) ApiPage   *page;

@end



//-------------------------線上是基類,線下是子類---------------------------------

#import "JsonCommonResultBase.h"

@interface ZTTestModel : SerializationBaseModel

@property (nonatomic,assign) NSInteger stuId;

@property (nonatomic,copy) NSString *stuName;

@property (nonatomic,copy) NSString *stuClassName;

@property (nonatomic,copy) NSString *stuScore;

@end

@interface ZTTestModelResult : JsonCommonResultBase

// BTW 實現多層級嵌套或者單數據模型也是沒有問題的,可參照上面代碼“api返回200數據格式”,這裡定義好就行了

@property (nonatomic,strong) NSMutableArray<ZTTestModel*> *result;

@end


// 重點來了,對於列表格式的result使用NSMutableArray<ZTTestModel*> *result類似定義後就搞定了嗎?那你就想太多了,我們還需要再實現代碼中添加字典轉化代碼,如下:
#import "ZTTestModelResult.h"

@implementation ZTTestModel

@end

@implementation ZTTestModelResult

// 拿出小本本記好筆記,針對列表格式的result必須添加這段代碼,單對象數據不需要
- (NSDictionary *)objectClassInArray{
    return @{@"result" : [ZTTestModel class]};
}

@end
返回數據基類與具體實現子類   那麼重點來了,我們知道AFNetworking調用API後返回的數據格式流為:NSData -> NSDictionary ,我們需要先將responseObject數據從NSData轉化為NSDictionary,這點在AFNetworkingManager中的已經寫明:
NSDictionary *resultDic = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableLeaves error:nil];

使用JSONObjectWithData後我們得到了NSDictionary格式的數據,但是我們需要的上面自定義對象模型數據啊!所以,你還需要一個序列化的工具在字典和模型間自如的轉化,它就是SerializationTools!

// 轉化為字典
- (NSMutableDictionary *)ToDictionary:(NSObject *)obj;

// 獲取屬性數組
- (NSMutableDictionary *)ToKeyDictionary:(NSObject *)obj;

// 字典填充對象
- (id)ToObjectOfDictionary:(NSDictionary *)dic class:(Class)class;

// 轉化為字典
- (NSData *)ToNSData:(NSObject *)obj;

// 字典填充對象
- (id)ToObjectOfData:(NSData *)data class:(Class)class;

/**
 *  字典數組轉換為對象數組
 *
 *  @param class 對象類別名稱
 *  @param array     數組
 *
 *  @return 對象數組
 */
-(NSMutableArray *)GetObjectListOfArray:(Class)class array:(NSArray *)array;

/**
 *  對象數組轉換為字典數組
 *
 *  @param array     對象數組
 *
 *  @return 字典數組
 */
-(NSArray *)GetDicListOfArray:(NSMutableArray *)array;

/**
 *  json格式字元串轉字典
 *
 *  @param jsonString <#jsonString description#>
 *
 *  @return <#return value description#>
 */
+ (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString;

/**
 *  字典轉json字元串
 *
 *  @param dic <#dic description#>
 *
 *  @return <#return value description#>
 */
+ (NSString*)dictionaryToJson:(NSDictionary *)dic;
序列化工具類

值得註意的是這段代碼,利用runtime獲取模型的欄位屬性(代碼段落,全部代碼請移步SerializationTools實現類.m)

// 獲取類成員變數和屬性列表,ivarsCnt為類成員數量
    unsigned int ivarsCnt = 0;
    
    Ivar *ivars = class_copyIvarList(cls, &ivarsCnt);
    
    // 只獲取類屬性列表
    //  unsigned int outCount = 0;
    //  objc_property_t *properties =class_copyPropertyList(cls, &outCount);
    
    // 遍歷成員變數列表,其中每個變數都是Ivar類型的結構體
    for (const Ivar *p = ivars; p < ivars + ivarsCnt; ++p) {
        
        Ivar const ivar = *p;
        
        // 獲取變數名
        NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
        // 若此變數未在類結構體中聲明而只聲明為Property,則變數名加首碼 '_'下劃線
        // 比如 @property(retain) NSString *abc;則 key == _abc;
        id value = [obj valueForKey:key];
        
        if([key characterAtIndex:0]=='_'){
            key=[key substringFromIndex:1];
        }
        if (value) {
            [dictionaryFormat setObject:[value class] forKey:key];
        } else {
            // 獲取類名
            NSString *className = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
            
            [dictionaryFormat setObject:[self GetClassByName:className] forKey:key];
        }
    }

通過序列化工具我們就可以很輕鬆的將字典轉化為自定義模型了!

id resultJson = [[SerializationTools sharedInstance] ToObjectOfDictionary:self.resultDic class:class];

3、Service邏輯計算與服務提供

service層主要是根據實際業務需求來定義的介面,實現邏輯計算與業務組裝,在這裡我舉一個例子如:

// 返回成功的結果、返回失敗的信息、請求超時的錯誤都能通過block實現反向傳值

.h文件

// GET
- (void)getStudentRecords:(NSInteger)offset
                   length:(NSInteger)length
               parentView:(UIView *)parentView
                 blockRtn:(void (^)(ZTTestModelResult *))blockRtn
               blockError:(void (^)(JsonCommonResultBase*))blockError
             blockTimeOut:(TimeOutCompletion)blockTimeOut;

-------------------------------分割線-------------------------------------

.m文件

- (void)getStudentRecords:(NSInteger)offset
                   length:(NSInteger)length
               parentView:(UIView *)parentView
                 blockRtn:(void (^)(ZTTestModelResult *))blockRtn
               blockError:(void (^)(JsonCommonResultBase*))blockError
             blockTimeOut:(TimeOutCompletion)blockTimeOut
{
    NSString *strUrl = @"對接的api url";
    
    [[ZTHttpManager sharedInstance]
     getDataToUrl:strUrl
     headers:nil
     params:nil
     parentView:parentView
     showShadow:YES
     class:[ZTTestModelResult class]
     blockRtn:blockRtn
     blockError:blockError
     blockTimeOut:blockTimeOut];
}

4、Controller層業務訴求

// Get
    [service getStudentRecords:0 length:10 parentView:self.view blockRtn:^(ZTTestModelResult *arryRtn) {
        
        // 回調成功,處理後續邏輯
        
    } blockError:^(JsonCommonResultBase *error) {
        
        // show message about error
        
    } blockTimeOut:^{
        
        // show message about timeout
    }];
    
    // Post
    [service postTest:@"param1" param2:@"param2" param3:@"param3" parentView:self.view blockRtn:^(JsonCommonResultBase *result) {
        
        // 回調成功,處理後續邏輯
        
    } blockError:^(JsonCommonResultBase *error) {
        
        // show message about error
        
    } blockTimeOut:^{
        
         // show message about timeout
    }];
    
    
    // upload
    [service uploadFileExpImage:[UIImage new] parentView:self.view blockProgress:^(NSString *progress) {
        
        // 上傳進度回調成功,處理顯示邏輯,註意刷新UI的操作一定要在主線程
        dispatch_async(dispatch_get_main_queue(), ^{
           
            //
        });
        
    } blockRtn:^(JsonCommonResultBase *rtn) {
        
        // 回調成功,處理後續邏輯
        
    } blockError:^(JsonCommonResultBase *error) {
        
        // show message about error
        
    } blockTimeOut:^{
        
        // show message about timeout
        
    }];

綜上所述,一個基本的基於MVC的網路數據訪問框架就完成了!

github地址:https://github.com/BeckWang0912/ZTAFNetworking.git   喜歡的話,請給個星星,您的鼓勵是我寫作的動力,謝謝!

BTW:demo中主要是框架的搭建和AFNetworking的封裝,不保證完全適用每個人的項目,我只提供設計思路,您來個性化,有不足之處還希望各位老司機多多包涵,畢竟我也是在iOS路上奮鬥不久的小白。 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 背景Lagom是JAVA系下響應式 微服務框架,在閱讀本文之前請先閱讀微服務架構設計,Lagom與其他微服務框架相比,與眾不同的特性包括:目前,大多數已有的微服務框架關註於簡化單個微服務的構建——這是比較容易的一部分內容。Lagom將其擴展到了微服務所構成的系統,這是大型的系統——也是較為困難的一部... ...
  • 1. 官網下載 wget http://mirror.bit.edu.cn/apache/hadoop/common /hadoop-3.0.0-alpha3/hadoop-3.0.0-alpha3.tar.gz ..註意下載二進位(省時間) 1解壓 tar -zxvf hadoop-3.0.0-a ...
  • 一,效果圖。 二,代碼。 ...
  • 1.對於strong:該對象強引用delegate,外界不能銷毀delegate對象,會導致迴圈引用(Retain Cycles) 因為我們一般代理的都是當前的控制器 比如scrollView.delegate = self;這時候就成了上面的一個圈的迴圈引用。如果上圖delegate為強指針,那麼 ...
  • Vysor破解助手(Vysor Crack Assistant),支持破解v1.6.6到v1.7.7之間的所有版本,含Linux版和macOS版。 ...
  • 自定義View有三個構造方法,它們的作用是不同的。 第一個是new 一個對象的時候調用。 第二個是在XML文件聲明的時候調用。 系統預設只會調用前兩個構造函數,至於第三個構造函數的調用,通常是我們自己在構造函數中主動調用的。 ...
  • 原圖 添加濾鏡後效果圖 ...
  • 1. 下載Charles Proxy 4.1.3版本,百度雲盤下載 或 去官網下載 2. 安裝後先打開Charles一次(Windows版可以忽略此步驟) 3. 在這個網站(http://charles.iiilab.com/)下載破解文件 charles.jar 4. 替換掉原文件夾里的charl ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...