AFHTTPSessionManager請(qǐng)求的管理者

AFNetworking源碼之Serialization模塊
本篇我們來(lái)看AFNetworking的下一個(gè)模塊Serialization
其中包括AFURLRequestSerialization和AFURLResponseSerialization兩個(gè)類
我們主要講AFURLRequestSerialization,因?yàn)锳FURLRequestSerialization的實(shí)現(xiàn)比AFURLResponseSerialization復(fù)雜得多,我們理解了AFURLRequestSerialization就不難理解AFURLResponseSerialization了。
AFURLRequestSerialization的作用是協(xié)助構(gòu)建NSURLRequest
其主要實(shí)現(xiàn)以下兩個(gè)功能:
1.構(gòu)建普通請(qǐng)求:格式化請(qǐng)求參數(shù),生成HTTP Header。
2.構(gòu)建multipart請(qǐng)求。
1.構(gòu)建普通請(qǐng)求
格式化請(qǐng)求參數(shù) 一般我們請(qǐng)求都會(huì)按key=value的方式帶上各種參數(shù),GET方法參數(shù)直接加在URL上,POST方法放在body上,NSURLRequest沒(méi)有封裝好這個(gè)參數(shù)的解析,只能我們自己拼好字符串。AFNetworking提供了接口,讓參數(shù)可以是NSDictionary, NSArray, NSSet這些類型,再由內(nèi)部解析成字符串后賦給NSURLRequest。
轉(zhuǎn)換分為三部分:
第一部分是用戶傳進(jìn)來(lái)的數(shù)據(jù),支持包含
NSArray,NSDictionary,NSSet這三種數(shù)據(jù)結(jié)構(gòu)。
第二部分是轉(zhuǎn)換成
AFNetworking內(nèi)自己的數(shù)據(jù)結(jié)構(gòu),每一個(gè)key-value對(duì)都用一個(gè)對(duì)象AFQueryStringPair表示,作用是最后可以根據(jù)不同的字符串編碼生成各自的key=value字符串。主要函數(shù)是AFQueryStringPairsFromKeyAndValue。
第三部分是最后生成
NSURLRequest可用的字符串?dāng)?shù)據(jù),并且對(duì)參數(shù)進(jìn)行url編碼,在AFQueryStringFromParametersWithEncoding這個(gè)函數(shù)里。
最后在把數(shù)據(jù)賦給NSURLRequest時(shí)根據(jù)不同的HTTP方法分別處理,對(duì)于
GET/HEAD/DELETE方法,把參數(shù)加到URL后面,對(duì)于其他如POST/PUT方法,把數(shù)據(jù)加到body上,并設(shè)好HTTP頭,告訴服務(wù)端字符串的編碼。

相關(guān)代碼:
創(chuàng)建管理路口:

- (instancetype)initWithBaseURL:(NSURL *)url
           sessionConfiguration:(NSURLSessionConfiguration *)configuration
{
    self = [super initWithSessionConfiguration:configuration];
    if (!self) {
        return nil;
    }

    // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected
    if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
        url = [url URLByAppendingPathComponent:@""];
    }

    self.baseURL = url;

    self.requestSerializer = [AFHTTPRequestSerializer serializer];
    self.responseSerializer = [AFJSONResponseSerializer serializer];

    return self;
}

構(gòu)建普通請(qǐng)求:格式化請(qǐng)求參數(shù),生成HTTP Header

self.requestSerializer = [AFHTTPRequestSerializer serializer];
+ (instancetype)serializer {
    return [[self alloc] init];
}

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

    self.stringEncoding = NSUTF8StringEncoding;

    self.mutableHTTPRequestHeaders = [NSMutableDictionary dictionary];

    // 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;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
#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
#pragma clang diagnostic pop
    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;
}

數(shù)據(jù)格式:

self.responseSerializer = [AFJSONResponseSerializer serializer];
+ (instancetype)serializer {
    return [self serializerWithReadingOptions:(NSJSONReadingOptions)0];
}

+ (instancetype)serializerWithReadingOptions:(NSJSONReadingOptions)readingOptions {
    AFJSONResponseSerializer *serializer = [[self alloc] init];
    serializer.readingOptions = readingOptions;

    return serializer;
}

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

    self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];

    return self;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 續(xù)AFNetworking核心類AFURLConnectionOperation的詳解本篇我們來(lái)看AFNetwor...
    小名一峰閱讀 1,396評(píng)論 0 0
  • 這是一篇團(tuán)隊(duì)的成員之一斯科特·舍伍德所寫(xiě)的教程,它是專門(mén)從事混合定位解決方案的動(dòng)態(tài)加載的定位軟件公司。 網(wǎng)絡(luò)——你...
    隨風(fēng)飄蕩的小逗逼閱讀 2,246評(píng)論 1 1
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,595評(píng)論 19 139
  • 編碼問(wèn)題一直困擾著開(kāi)發(fā)人員,尤其在 Java 中更加明顯,因?yàn)?Java 是跨平臺(tái)語(yǔ)言,不同平臺(tái)之間編碼之間的切換...
    x360閱讀 2,581評(píng)論 1 20
  • 最近我讀了一本帶有自傳性質(zhì)的家庭小說(shuō)《小婦人》,作者是美國(guó)女作家路易斯?梅?奧爾科特(1832—1888...
    ZH玉娟閱讀 1,346評(píng)論 1 2

友情鏈接更多精彩內(nèi)容