OC-AFNetworking

文章目錄

  • AFNetworking
    • 簡介
    • 問題
      • 🤔
      • 優化策略
    • 解決AFNetworking局限性
      • 使用單例進行網絡請求的優勢
      • 使用單例進行網絡請求的風險
      • 最優使用
    • 使用
    • 參數講解
    • POST請求

AFNetworking

簡介

這篇文章旨在實現使用AFNetworking設置一個集中的單通道網絡對象,該對象與MVC組建分離,可以在整個解耦架構應用程序中重復使用

資料來源:https://www.toptal.com/ios/afnetworking-tutorial-with-a-singleton-class?utm_source=chatgpt.com

雖然蘋果抽象的許多iOS SDK在管理移動硬件的許多復雜性方面做的很好,但是在某些情況下為了保持SDK的靈活性,使用會很復雜。AFNetworking作為開源框架之一,簡化了developer的日程任務。 他簡化了RESTful API網絡,并創建了具有成功、進度、和失敗的模塊化請求/響應模式。消除了對開發人員實施的委托方法和自定義請求/連接設置的需求,并且可以非常快速的包含在任何類中

問題

雖然AFN是一個功能強大、模塊化的網絡庫,但是也會存在一些低效實施。如下

🤔

  • 分散的網絡請求邏輯
    • 單個視圖控制器包含多個幾乎相同的請求,難以復用,后期維護成本高
    • 如果API發生變更,需要逐個排查所有使用的地方,容易遺漏
  • 共享狀態混亂
    • 一些通用參數可能分散在不同的控制器中,容易出現不一致或者同步問題
  • 職責分離不清
    • 視圖控制器承擔了數據獲取的職責,導致控制器代碼臃腫
  • 拓展性不足
    • 如果API發生版本化或者新增參數,修改成本大

優化策略

  • 集中化網絡層設計
    • 創建獨立的NetworkManager或APIClient集中管理所有請求
    • 將通用的請求頭、參數注入邏輯同意處理
  • 抽象請求方法
  • 引入模型層
    • 使用YY_Model等庫,將API響應解析為強類型模型對象
    • 控制器只關心模型,不關心JSON結構
  • 支持版本或者參數設置
    • 在APIClient內部設計時預留一些字段

解決AFNetworking局限性

我們可以通過創建一個網絡單例類來集中處理請求、響應以及其參數

蘋果官方的原話:“A singleton object provides a global point of access to the resources of its class. Singletons are used in situations where this single point of control is desirable, such as with classes that offer some general service or resource. You obtain the global instance from a singleton class through a factory method. – Apple“

就是單例模式的介紹,想了解的可以看筆者前面有關單例模式的文章

使用單例進行網絡請求的優勢

  • 全局唯一,是靜態初始化。保證了所有類訪問的都是同一個實例,避免了因為不同實例不同步導致的奇怪bug
  • 同義API的調用和速率限制。單例可以集中管理請求隊列和節流邏輯,防止因多個視圖控制器并發請求導致速率限制
  • 集中化配置管理
  • 重復利用公共屬性。通用的請求頭、超時設置、解析策略都能復用。
  • 延遲加載、節省內存。單例在第一次使用前不加載,不占用內存
  • 解耦視圖與網絡層,即使視圖控制器銷毀,網絡請求仍能繼續,避免了因為界面消失導致網絡請求中斷的問題
  • 統一日志與錯誤處理
  • 跨項目復用

使用單例進行網絡請求的風險

  • 可能承擔過多職責,我們在使用單例時,每個單例應該只做一件事
  • 無法繼承,單例不能被子類化,如果未來需要拓展,不夠靈活。可以通過使用協議和依賴注入提供可替換的實現
  • 共享狀態可能被意外修改
  • 長時間持有大量數據,不釋放。可以定期清理緩存或者重置單例內部狀態

最優使用

  • 單一職責原則
  • 線程安全,使用GCD或加鎖
  • 輕量化存儲,單例只存放必要的全局設置
  • 支持依賴注入
  • 提供重置能力,在必要時可以手動清空狀態

使用

我們實現一個簡單的GET請求來演示AFNetworking的效果

首先,我們先為項目導入需要的AFNetworking第三方庫,這里的操作就略過了,我們直接進入正文

  • 創建單例類, 并實現GET方法
#import <Foundation/Foundation.h>
#import "AFNetworking.h"
NS_ASSUME_NONNULL_BEGIN@interface NetworkManager : NSObject
@property (nonatomic, strong)AFHTTPSessionManager* sessionManager;+ (instancetype)sharedManager;- (void)GET:(NSString* ) URLString parameters:(nullable id)parameters headers:(nullable NSDictionary<NSString *,NSString *> *)headers progress:(nullable void (^)(NSProgress * _Nonnull))downloadProgress success:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure;@endNS_ASSUME_NONNULL_END
//  Created by xiaoli pop on 2025/9/15.
//#import "NetworkManager.h"
static NetworkManager* sharedManager = nil;
@implementation NetworkManager
+ (instancetype)sharedManager {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{sharedManager = [[super allocWithZone:NULL] init];});return sharedManager;
}+ (instancetype)allocWithZone:(struct _NSZone *)zone {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{sharedManager = [super allocWithZone:zone];});return sharedManager;
}- (instancetype)init {if (self = [super init]) {self.sessionManager = [AFHTTPSessionManager manager];self.sessionManager.requestSerializer = [AFJSONRequestSerializer serializer];self.sessionManager.requestSerializer.timeoutInterval = 15.0;self.sessionManager.responseSerializer = [AFJSONResponseSerializer serializer];self.sessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/plain", @"text/html", nil];}return self;
}- (void)GET:(NSString *)URLString parameters:(id)parameters headers:(NSDictionary<NSString *,NSString *> *)headers progress:(void (^)(NSProgress * _Nonnull))downloadProgress success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure {[self.sessionManager GET:URLString parameters:parameters headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {if (success) {success(task, responseObject);}} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {if (failure) {failure(task, error);}}];
}@end
  • 使用
 NSString* str = @"安康";NSString* urlString  = [NSString stringWithFormat:@"https://api.weatherapi.com/v1/forecast.json?key=8f123b0cdc654b149aa92217252607&q=%@&days=3&lang=zh",str];urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];[[NetworkManager sharedManager] GET:urlString parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {NSLog(@"%@", responseObject);} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {NSLog(@"error");}];

我們對比一下原生的網絡請求

- (void)creatURL {NSLog(@"!!!");NSString* str = @"安康";NSString* urlString  = [NSString stringWithFormat:@"https://api.weatherapi.com/v1/forecast.json?key=8f123b0cdc654b149aa92217252607&q=%@&days=3&lang=zh",str];urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];NSURL* url = [NSURL URLWithString:urlString];NSURLRequest* request = [NSURLRequest requestWithURL:url];NSURLSession* session = [NSURLSession sharedSession];NSURLSessionTask* task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {if (!error && data) {NSError* jsonError;NSDictionary* jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];if (!jsonError && [jsonDict isKindOfClass:[NSDictionary class]]) {// NSLog(@"%@", jsonDict);Model* model = [Model yy_modelWithDictionary:jsonDict];NSLog(@"%@", model.current[@"cloud"]);NSLog(@"%@", model);}} else {NSLog(@"ERROR: %@", error);}}];[task resume];
}

顯而易見,當我們使用一個單例類來處理網絡申請時,代碼邏輯更清晰,后期維護更方便

參數講解

  • URL
    • NSURL或者其字符串表示形式
    • 描述:網絡資源的地址,制定了請求的目標位置
  • parameters
    • 類型:NSDictionary
    • 描述:字典,用于傳遞請求的參數,在GET請求中這些參數會附加到URL字符串中,以便于服務器根據這些參數返回對應數據
  • progress
    • 類型:通常是一個void(^)(NSprogress* downloadProgress)類型的塊
    • 這個參數用于跟蹤下載進度,他接收一個NSProgress對象,該對象包含了已下載的數據量、總數據量等信息。。可以在此實現更新進度條等操作,不需要可以傳nil
  • headers
    • NSDictionary
    • 用于設置HTTP請求頭部信息。
    • 每個請求頭都是一對鍵值對,
  • success
    • 類型:void(^)NSURLSessionDataTask* task, id responseObject)類型的塊
    • 請求成功后的回調塊,通常接受兩個參數,一個是包含響應數據的NSURLSessionDataTask對象,一個是響應數據,通常是一個NSDictionary或其他數據結構
  • failure
    • 失敗后的回調塊,第一個參數也是包含請求任務的NSURLSessionDataTask對象,第二個參數是一個NSError對象,包含了請求失敗的信息

POST請求

在單例中:

- (void)POST:(NSString *)URLString parameters:(id)parameters headers:(NSDictionary<NSString *,NSString *> *)headers progress:(void (^)(NSProgress * _Nonnull))uploadProgress success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure {[self.sessionManager POST:URLString parameters:parameters headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {if (success) {success(task, responseObject);}} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {if (failure) {failure(task, error);}}];
}

使用:

- (void)LoginWithUsrname:(NSString* )username withPassword:(NSString* )password {NSString* urlString = @"https://......./login";NSDictionary* parameters = @{@"username" : username , @"password" : password};[[NetworkManager sharedManager] POST:urlString parameters:parameters headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {NSLog(@"%@", responseObject);} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {NSLog(@"%@", error);}];
}

APIURL是接口的基本路徑,而parameters是傳給接口的查詢參數或請求體,AFNetworking會自動把parameters序列化并拼接到URL或者body,前提是必須得有一個基礎URL來承接這些參數

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/923601.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/923601.shtml
英文地址,請注明出處:http://en.pswp.cn/news/923601.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【數據結構】跳表

目錄 1.什么是跳表-skiplist 2.skiplist的效率如何保證&#xff1f; 3.skiplist的實現 3.1節點和成員設計 3.2查找實現 3.3前置節點查找 3.4插入實現 3.5刪除實現 3.6隨機層數 3.7完整代碼 4.skiplist跟平衡搜索樹和哈希表的對比 1.什么是跳表-skiplist skiplist是由…

html實現右上角有個圖標,鼠標移動到該位置出現手型,點擊會彈出登錄窗口。

寫了一段html代碼實現的效果&#xff1a;實現右上角有個圖標&#xff0c;鼠標移動到該位置出現手型&#xff0c;點擊會彈出登錄窗口。功能實現前端&#xff0c;沒有實現后端。<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF…

STM32G4 電流環閉環(二) 霍爾有感運行

目錄一、STM32G4 電流環閉環(二) 霍爾有感運行2. 霍爾有感運行附學習參考網址歡迎大家有問題評論交流 (* ^ ω ^)一、STM32G4 電流環閉環(二) 霍爾有感運行 2. 霍爾有感運行 文章使用的BLDC在定子側以互差120電角度的位置安裝三個霍爾元件Ha&#xff0c;Hb&#xff0c;Hc。當…

展示框選擇

好的&#xff0c;非常感謝您提供更詳細的項目情況。這是一個非常典型的父子組件通信場景。 根據您的新需求&#xff0c;我將對代碼進行重構&#xff1a; FaultSelect.vue (子組件): 這個組件現在將變得更加“純粹”。它只負責自身的下拉框邏輯&#xff0c;不關心外部按鈕&#…

第5課:上下文管理與狀態持久化

第5課:上下文管理與狀態持久化 課程目標 掌握上下文存儲和檢索策略 學習會話狀態管理 了解數據持久化方案 實踐實現上下文管理系統 課程內容 5.1 上下文管理基礎 什么是上下文管理? 上下文管理是Agent系統中維護和利用歷史信息的能力,包括: 對話歷史:用戶與Agent的交互…

計算機畢業設計 基于大數據技術的醫療數據分析與研究 Python 大數據畢業設計 Hadoop畢業設計選題【附源碼+文檔報告+安裝調試】

博主介紹&#xff1a;?從事軟件開發10年之余&#xff0c;專注于Java技術領域、Python、大數據、人工智能及數據挖掘、小程序項目開發和Android項目開發等。CSDN、掘金、華為云、InfoQ、阿里云等平臺優質作者? &#x1f345;文末獲取源碼聯系&#x1f345; &#x1f447;&…

K8S集群管理(2)

目錄 1.什么是Pod的根容器&#xff1f; 2.解釋Pod的生命周期。 3.Init類型容器有什么特點&#xff0c;主要用途&#xff1f; 4.Sidecar類型容器和Init容器的區別在哪&#xff1f; 5.什么是靜態Pod&#xff1f; 6.說明K8s控制器的作用&#xff1f; 7.什么是ReplicaSet&#xff0…

視頻全模態referring分割:Ref-AVS: Refer and Segment Objects in Audio-Visual Scenes

一、TL&#xff1b;DR 為什么要做&#xff1a;傳統的referring分割無法使用音頻模態&#xff0c;本文提出Reference audio-visual Segmentation本文怎么做&#xff1a;構建首個 Ref-AVS 基準數據集通過充分利用多模態提示&#xff0c;將音頻信息通過和文本融合作為載體&#x…

A股大盤數據-20250916分析

&#x1f4ca; 一、大盤數據深度分析1.1 &#x1f9ee; 市場活躍度與資金流向總成交額&#xff1a;滬深京合計約 2.37萬億元&#xff0c;市場交投活躍&#xff0c;深市成交&#xff08;13516.4億&#xff09;明顯高于滬市&#xff08;9897.9億&#xff09;&#xff0c;顯示中小…

[計算機畢業設計]基于深度學習的噪聲過濾音頻優化系統研究

前言 &#x1f4c5;大四是整個大學期間最忙碌的時光,一邊要忙著備考或實習為畢業后面臨的就業升學做準備,一邊要為畢業設計耗費大量精力。近幾年各個學校要求的畢設項目越來越難,有不少課題是研究生級別難度的,對本科同學來說是充滿挑戰。為幫助大家順利通過和節省時間與精力投…

貪心算法應用:NFV功能部署問題詳解

Java中的貪心算法應用&#xff1a;NFV功能部署問題詳解 1. NFV功能部署問題概述 網絡功能虛擬化(NFV, Network Function Virtualization)是一種將傳統網絡設備功能從專用硬件轉移到虛擬化軟件的技術。在NFV功能部署問題中&#xff0c;我們需要將各種虛擬網絡功能(VNFs)部署到有…

SeriLog測試

安裝Serilog.Sinks.Seq(5.2.3.0)&#xff0c;Serilog.Sinks.File(7.0.0) 下載Seq安裝包并安裝&#xff08;https://datalust.co/download&#xff09; 代碼如下&#xff1a; private Logger _logger;private void button1_Click(object sender, EventArgs e){_logger new Lo…

HarmonyOS 5.0應用開發——V2裝飾器@param的使用

【高心星出品】 文章目錄V2裝飾器param的使用概念使用方法案例V2裝飾器param的使用 概念 在鴻蒙ArkTS開發中&#xff0c;Param裝飾器是組件間狀態管理的重要工具&#xff0c;主要用于父子組件間的單向數據傳遞&#xff0c;這一點與V1中的prop類似。 Param裝飾的變量支持本地…

SLAM | 無人機視覺/激光雷達集群SLAM技術進展綜述

主要內容如下: 無人機集群SLAM技術概述:介紹無人機集群SLAM的基本概念、重要性及面臨的挑戰,使用表格對比不同傳感器配置的特點。 多傳感器融合與協同SLAM架構:分析集中式、分布式和混合式協同架構的特點,使用表格對比不同架構的優缺點。 視覺協同SLAM的技術進展:總結直接…

信息化系統運維文檔資料,運維服務方案,運維巡檢方案

1、系統服務內容?1.1 服務目標?1.2 信息資產統計服務?1.3 網絡與安全系統運維服務?1.4 主機與存儲系統運維服務?1.5 數據庫系統運維服務?1.6 中間件運維服務?2、服務管理制度規范?2.1 服務時間管理?2.2 運維人員行為規范?2.3 現場服務支持規范?2.4 問題記錄與歸檔規…

JavaScript——document對象

DOM 是 document object model&#xff08;文檔對象模型&#xff09;的縮寫。它是一種與平臺、語言無關的接口&#xff0c;允許程序動態地訪問或更新 HTML、XML 文檔的內容、結構和樣式&#xff0c;且提供了一系列的函數和對象來實現增、刪、改、查操作。DOM 對象的一個特點是&…

UART,IIC,SPI總線(通信協議)

嵌 入 式 軟 件 筆 試 題要求&#xff1a;閉卷考試&#xff08;不能翻書、不能開電腦&#xff09;&#xff1b;作答時間50分鐘&#xff1b;共10道題目。volatile的作用有哪些volatile&#xff1a; 防止編譯器對代碼進行優化&#xff0c;直接從內存中取最新的值 應用場景&#x…

通信模組性能調優

通信模組性能調優 1 背景 2 高通平臺軟硬加速 2.1 NSS 2.2 SFE 2.3 PPE 3 CPU 負載均衡設置 3.1 啟用內核 RPS&RFS 功能 3.2 網卡隊列修改建議 3.3 調整負載前后的 CPU 使用對比 3.4 網卡中斷均衡 3.4.1 netdev_max_backlog 3.4.2 中斷綁核 3.5 CPU性能模式 3.6 熱管理 3.7…

消息隊列kafka的事務特性

kafka的java客戶端producer也支持事務消息嗎&#xff1f;具體是啥事務呢&#xff1f; 是的&#xff0c;Kafka的Java客戶端Producer確實支持事務消息。讓我詳細解釋Kafka事務的概念和使用方法。 Kafka事務的主要特點&#xff1a; Producer Transactions&#xff1a;確保多個消息…

用Python實現自動化的Web測試(Selenium)

Python作為數據科學和自動化領域的主流語言&#xff0c;在網絡爬蟲開發中占據著重要地位。本文將全面介紹Python爬蟲的技術棧、實現方法和最佳實踐。爬蟲技術概述網絡爬蟲&#xff08;Web Crawler&#xff09;是一種按照特定規則自動抓取互聯網信息的程序。它可以自動化地瀏覽網…