1. 程式人生 > >AFNetworking3.1.0原始碼分析(四)詳解AFHTTPRequestSerializer 之初始化方法

AFNetworking3.1.0原始碼分析(四)詳解AFHTTPRequestSerializer 之初始化方法

1:類圖介紹

在AFHTTPSessionManager 初始化方法中可以看到 AFNetworking 預設使用的網路請求序列化類是AFHTTPRequestSerializer,一下是關於它的類圖:


2:類功能分析:

 一:初始化函式:

- (instancetype)init {
    self = [super init];
    if (!self) {
        return nil;
    }

    ①
    
    self.stringEncoding = NSUTF8StringEncoding;

    ②

    self.mutableHTTPRequestHeaders = [NSMutableDictionary dictionary];
    self.requestHeaderModificationQueue = dispatch_queue_create("requestHeaderModificationQueue", DISPATCH_QUEUE_CONCURRENT);
    // Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
    NSMutableArray *acceptLanguagesComponents = [NSMutableArray array];
    [[NSLocale preferredLanguages] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        float q = 1.0f - (idx * 0.1f);
        [acceptLanguagesComponents addObject:[NSString stringWithFormat:@"%@;q=%0.1g", obj, q]];
        *stop = q <= 0.5f;
    }];
    [self setValue:[acceptLanguagesComponents componentsJoinedByString:@", "] forHTTPHeaderField:@"Accept-Language"];

    ③

    NSString *userAgent = nil;
#if TARGET_OS_IOS
    // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
    userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)☺", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]];
#elif TARGET_OS_WATCH
    // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
    userAgent = [NSString stringWithFormat:@"%@/%@ (%@; watchOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[WKInterfaceDevice currentDevice] model], [[WKInterfaceDevice currentDevice] systemVersion], [[WKInterfaceDevice currentDevice] screenScale]];
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
    userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]];
#endif
    
    if (userAgent) {

        
        if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) {
            NSMutableString *mutableUserAgent = [userAgent mutableCopy];
            if (CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false)) {
                userAgent = mutableUserAgent;
            }
        }
        [self setValue:userAgent forHTTPHeaderField:@"User-Agent"];
    }

    ④

    // HTTP Method Definitions; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
    self.HTTPMethodsEncodingParametersInURI = [NSSet setWithObjects:@"GET", @"HEAD", @"DELETE", nil];

    ⑤

    self.mutableObservedChangedKeyPaths = [NSMutableSet set];
    for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
        if ([self respondsToSelector:NSSelectorFromString(keyPath)]) {
            [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:AFHTTPRequestSerializerObserverContext];
        }
    }
    return self;
}


①:設定預設的編碼格式是utf8

②:根據系統的語言設定http請求頭欄位Accept-Language 的值,eg(zh-CN;q=0.8) 解釋後面的q表示前面語言的權值,如果是多種語言,伺服器可以根據圈值的大小優先響應哪種請求。具體含義可參見文章

③:這個步驟的操作意思是刪除user-agent 中所有的不能ascii編碼的字元,詳細的函式介紹:

CFStringTransform(CFMutableStringRef string, CFRange *range, CFStringRef transform, Boolean reverse)對於此函式的詳細介紹可參考文章,下面我將使用例項介紹此函式的威力,拿AFNetworking中使用舉例。

   1:將中文變成漢語拼音帶音調程式碼如下:

NSString *userAgent = @"中華人民共和國";
    NSMutableString *mutableUserAgent = [userAgent mutableCopy];
    CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin", false);
    NSLog(@"%@",mutableUserAgent);
輸出結果:
2016-12-06 21:06:38.925 test2[15785:400567] zhōng huá rén mín gòng hé guó
2:將中文變成漢語拼音不帶音調程式碼如下:
 NSString *userAgent = @"中華人民共和國";
    NSMutableString *mutableUserAgent = [userAgent mutableCopy];
    CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII", false);
    NSLog(@"%@",mutableUserAgent);
    NSLog(@"%@",userAgent);
輸出結果:
2016-12-06 21:09:41.519 test2[15858:404061] zhong hua ren min gong he guo
3:移除所有非ASCII(0-255包含擴充套件字元)值範圍的所有字元程式碼如下:


輸出結果:

2016-12-06 21:12:38.127 test2[15936:407291] 1Aa3
解釋為什麼會有3,先參考文章獲取包含中英文表情混合字元中的每個字元裡面同時對每個字元的unicode值進計算,計算之後3的值(153,這個字元3是在mac上使用搜狗輸入法輸入)是在ASCII(0-255包含擴充套件字元)範圍之內。

4:AFNetworking的使用解釋:

CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false)
輸出的效果是以上3點的結合(層層過濾):
2016-12-06 21:44:40.206 test2[16642:436125] 1Aa a3zhong hua ren min gong he guo

④:http請求方法中 GET HEAD DELETE 此三種方法是對引數直接放在URI中,因此需要設定,對這幾種方式請求的引數編碼

⑤:主要是對系統的函式的監聽(KVO)系統的函式如下程式碼(_AFHTTPRequestSerializerObservedKeyPaths):

static NSArray * AFHTTPRequestSerializerObservedKeyPaths() {
    static NSArray *_AFHTTPRequestSerializerObservedKeyPaths = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _AFHTTPRequestSerializerObservedKeyPaths = @[NSStringFromSelector(@selector(allowsCellularAccess)), NSStringFromSelector(@selector(cachePolicy)), NSStringFromSelector(@selector(HTTPShouldHandleCookies)), NSStringFromSelector(@selector(HTTPShouldUsePipelining)), NSStringFromSelector(@selector(networkServiceType)), NSStringFromSelector(@selector(timeoutInterval))];
    });

    return _AFHTTPRequestSerializerObservedKeyPaths;
}


相關推薦

AFNetworking3.1.0原始碼分析AFHTTPRequestSerializer 初始方法

1:類圖介紹 在AFHTTPSessionManager 初始化方法中可以看到 AFNetworking 預設使用的網路請求序列化類是AFHTTPRequestSerializer,一下是關於它的類圖: 2:類功能分析:  一:初始化函式: - (instancetyp

AFNetworking3.1.0原始碼分析整體框架和功能模組

簡介 1:基於系統NSURLSession類族封裝完成HPPT/HPPTS(GET,PUT,PSOT,DELEATE,HEAD)網路請求 2:擴充套件部分UIKit控制元件,比如擴充套件UIIMag

AFNetWorking(3.0)原始碼分析——AFHTTPSessionManager(2)

在上一篇部落格中,我們分析了AFHTTPSessionManager,以及它是如何實現GET/HEAD/PATCH/DELETE相關介面的。 我們還剩下POST相關介面沒有分析,在這篇部落格裡面,我們就來分析一下POST相關介面是如何實現的。 multipart/form-data請

SpringBoot2.0原始碼分析:spring-data-jpa分析

SpringBoot具體整合rabbitMQ可參考:SpringBoot2.0應用(四):SpringBoot2.0之spring-data-jpa JpaRepositories自動注入 當專案中存在org.springframework.data.jpa.repository.JpaRepositor

Spring原始碼分析-Spring IoC容器的初始No.1

Spring IoC容器的初始化 Spring原始碼分析(一)中提到了很多類,比如BeanDefinition、BeanDefinitionReader、BeanDefintionParser、BeanWrapper等都是ApplicationContext中

Netflix Eureka原始碼分析7——eureka client啟動環境初始流程

eureka-examples,有一個類,ExampleEurekaClient,就是一個自帶的例子,如果是一個eureka服務,一定會有一個eureka client,服務例項啟動的時候,一定會啟動eureka client,eureka client去向eureka se

Spring原始碼分析-Spring IoC容器的初始No.2

Spring原始碼分析(一)-Spring IoC容器的初始化No.1中已經分析了Bean的載入過程,本章將分析Bean的例項化過程 本章圍繞refresh().finishBeanFactoryInitialization(beanFactory)方法,

SpringBoot啟動流程分析:IoC容器的初始過程

SpringBoot系列文章簡介 SpringBoot原始碼閱讀輔助篇:   Spring IoC容器與應用上下文的設計與實現 SpringBoot啟動流程原始碼分析: SpringBoot啟動流程分析(一):SpringApplication類初始化過程 SpringBoot啟動流程分析(二)

Flume NG原始碼分析使用ExecSource從本地日誌檔案中收集日誌

常見的日誌收集方式有兩種,一種是經由本地日誌檔案做媒介,非同步地傳送到遠端日誌倉庫,一種是基於RPC方式的同步日誌收集,直接傳送到遠端日誌倉庫。這篇講講Flume NG如何從本地日誌檔案中收集日誌。 ExecSource是用來執行本地shell命令,並把本地日誌檔案中的資料封裝成Event

OpenCV學習筆記30KAZE 演算法原理與原始碼分析KAZE特徵的效能分析與比較

      KAZE系列筆記: 1.  OpenCV學習筆記(27)KAZE 演算法原理與原始碼分析(一)非線性擴散濾波 2.  OpenCV學習筆記(28)KAZE 演算法原理與原始碼分析(二)非線性尺度空間構

GCC原始碼分析——優化

原文連結:http://blog.csdn.net/sonicling/article/details/7916931 一、前言 本篇只介紹一下框架,就不具體介紹每個步驟了。 二、Pass框架 上一篇已經講了gcc的中間語言的表現形式。gcc 對中間語言

YOLOv2原始碼分析

文章全部YOLOv2原始碼分析 0x01 backward_convolutional_layer void backward_convolutional_layer(convolutional_layer l, network

AFNetWorking(3.0)原始碼分析——AFHTTPRequestSerializer & AFHTTPResponseSerializer

在前面的幾篇部落格中,我們分析了AFURLSessionMangerd以及它的子類AFHTTPSessionManager。我們對AF的主要兩個類,有了一個比較全面的瞭解。 對於AFHTTPSessionManager,當其在要傳送請求時,會呼叫AFHTTPRequestSerial

Redis5.0原始碼解析----------跳躍表

基於Redis5.0 跳躍表(skiplist)是一種有序資料結構, 它通過在每個節點中維持多個指向其他節點的指標, 從而達到快速訪問節點的目的 跳躍表支援平均 O(log N) 最壞 O(N) 複雜度的節點查詢, 還可以通過順序性操作來批量處理節點。 在大部分

jdk原始碼分析——垃圾收集器與記憶體分配策略

本章介紹的垃圾收集器與記憶體分配策略主要就三點。 第一點:垃圾收集(垃圾回收)。問題:哪些記憶體需要回收?什麼時候回收?如何回收? 第二點:介紹垃圾收集器。問題:有幾種型別是垃圾收集器?根據第一點的介紹,屬於那種型別的? 第三點:記憶體分配。問題:怎麼分配的? 一、垃

Java多執行緒Condition實現原理和原始碼分析

章節概覽、 1、概述 上面的幾個章節我們基於lock(),unlock()方法為入口,深入分析了獨佔鎖的獲取和釋放。這個章節我們在此基礎上,進一步分析AQS是如何實現await,signal功能。其功能上和synchronize的wait,notify一樣。

我對hyperledger fabric1.1.0的執著:部署單機多節點網路

1、生成證書檔案 (1.1)環境清理 接上一篇,已跑通e2e_cli案例,此處需要執行以下命令進行環境清理: cd /opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli bash network_

Muduo網路庫原始碼分析EventLoopThread和EventLoopThreadPool的封裝

muduo的併發模型為one loop per thread+ threadpool。為了方便使用,muduo封裝了EventLoop和Thread為EventLoopThread,為了方便使用執行緒

spring boot 2.0 原始碼分析

在學習spring boot 2.0原始碼之前,我們先利用spring initializr快速地建立一個基本的簡單的示例: 1.先從建立示例中的main函式開始讀起: package com.example; import org.springfra

HashMap原始碼分析put-jdk8-紅黑樹的引入

HashMap jdk8以後他的邏輯結構發生了一點變化: 大概就是這個意思: 當某一個點上的元素數量打到一定的閾值的時候,連結串列會變成一顆樹,這樣在極端情況下(所有的元素都在一個點上,整個就以連結串列),一些操作的時間複雜度有O(n)變成了O(logn)。 分析原始碼