iOS源碼補(bǔ)完計(jì)劃--AFNetworking 3.1.0源碼研讀

參拜一下AFNetworking的源碼兴喂。
第四篇源碼、暫時(shí)來(lái)看也是iOS方向的最后一篇焚志、擼完準(zhǔn)備趁著熱乎擼一擼網(wǎng)絡(luò)協(xié)議衣迷。


目錄

  • 準(zhǔn)備工作

  • 功能模塊

  • AFURLSessionManager/AFHTTPSessionManager

    • 核心代碼
    • 一些比較有意思的東西
      • 在監(jiān)聽(tīng)屬性的時(shí)候、可以用NSStringFromSelector(@selector(xxx))這種方式來(lái)自動(dòng)提示娩嚼。
      • 功能AIP分層
      • 如何防止block循環(huán)引用
      • 把NSURLSession眾多代理轉(zhuǎn)化成了block
      • 消除編譯器clang警告
      • 正則的簡(jiǎn)便寫法
      • 如何做到對(duì)外只讀蘑险、對(duì)內(nèi)讀寫
  • AFNetworkReachabilityManager

    • 核心代碼
      • 四種網(wǎng)絡(luò)狀態(tài)
      • 開(kāi)始暫停
      • 狀態(tài)改變的回調(diào)block
    • 知識(shí)點(diǎn)
      • 關(guān)于FOUNDATION_EXPORT和UIKIT_EXTERN的選擇
      • .#if - #esle - #endif
      • 注冊(cè)鍵值依賴
  • AFSecurityPolicy

    • 核心代碼
      • .cer文件在iOS里如何使用的
      • 三種驗(yàn)證模式
    • 知識(shí)點(diǎn)
      • __Require_Quiet判斷
  • AFHTTPRequestSerializer

  • AFHTTPResponseSerializer

    • 核心代碼
      • AFURLResponseSerialization協(xié)議以及其解碼方法
    • 知識(shí)點(diǎn)
      • 協(xié)議的應(yīng)用
      • 如何在一個(gè)方法中返回兩個(gè)NSError
      • NSIndexSet對(duì)象
      • 服務(wù)器返回的圖片是壓縮過(guò)的
  • 參考資料


準(zhǔn)備工作

GitHub

使用版本3.1.0

PODS:
  - AFNetworking (3.1.0):
    - AFNetworking/NSURLSession (= 3.1.0)
    - AFNetworking/Reachability (= 3.1.0)
    - AFNetworking/Security (= 3.1.0)
    - AFNetworking/Serialization (= 3.1.0)
    - AFNetworking/UIKit (= 3.1.0)
  - AFNetworking/NSURLSession (3.1.0):
    - AFNetworking/Reachability
    - AFNetworking/Security
    - AFNetworking/Serialization
  - AFNetworking/Reachability (3.1.0)
  - AFNetworking/Security (3.1.0)
  - AFNetworking/Serialization (3.1.0)
  - AFNetworking/UIKit (3.1.0):
    - AFNetworking/NSURLSession

DEPENDENCIES:
  - AFNetworking

SPEC CHECKSUMS:
  AFNetworking: 5e0e199f73d8626b11e79750991f5d173d1f8b67

PODFILE CHECKSUM: 75e1e619317fd130ee494d35ddff3d9c614c4390

COCOAPODS: 1.3.1

推薦在看AFN之前、先了解一下NSURLSession

不然感覺(jué)會(huì)看的一頭霧水岳悟、也體會(huì)不到AFN的偉大之處

《iOS基礎(chǔ)深入補(bǔ)完計(jì)劃--網(wǎng)絡(luò)模塊NSURLSession概述》


功能模塊


除了這四個(gè)服務(wù)性模塊之外佃迄、UIKit文件夾下基本是對(duì)各種UI控件的擴(kuò)展泼差。


AFURLSessionManager/AFHTTPSessionManager

AFURLSessionManager流程

承接了主要的網(wǎng)絡(luò)傳輸任務(wù)、實(shí)現(xiàn)了NSURLSession絕大部分的代理方法呵俏。

  • 核心代碼

可以移步:《iOS源碼補(bǔ)完計(jì)劃--AFNetworking(一)》

一些比較有意思的東西

  • 在監(jiān)聽(tīng)屬性的時(shí)候堆缘、可以用NSStringFromSelector(@selector(xxx))這種方式來(lái)自動(dòng)提示。

因?yàn)閷傩员旧砭褪桥c其get方法同名普碎、可以降低出錯(cuò)概率吼肥。

[self.uploadProgress addObserver:self
                          forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
                             options:NSKeyValueObservingOptionNew
                             context:NULL];
  • 功能AIP分層

AFURLSessionManager實(shí)現(xiàn)了所有的NSURLSessionDelegate
但同時(shí)又將其中某些需要處理復(fù)雜邏輯的代理傳遞給了AFURLSessionManagerTaskDelegate麻车。
使得代碼更清晰缀皱、邏輯更明確。
需要注意的是动猬、AFURLSessionManagerTaskDelegate完全包裹在了AFURLSessionManager內(nèi)部啤斗、外界完全感受到他的存在。但是又能做數(shù)據(jù)處理赁咙、這個(gè)架構(gòu)設(shè)計(jì)真心很贊钮莲。
除此之外、AFURLSessionManagerAFHTTPSessionManager之間也做了很好的分層彼水。
你可以單獨(dú)使用AFURLSessionManager進(jìn)行網(wǎng)絡(luò)會(huì)話崔拥、也可以通過(guò)AFHTTPSessionManager更好的使用AFURLSessionManager進(jìn)行HTTP請(qǐng)求。

  • 如何防止block循環(huán)引用

其實(shí)我?guī)啄昵熬吐?tīng)說(shuō)AFN可以防止循環(huán)引用凤覆、但是一直沒(méi)看链瓦。
今天找了找發(fā)現(xiàn)似乎已經(jīng)沒(méi)有了這段代碼
所以個(gè)人推測(cè)現(xiàn)在不會(huì)引起循環(huán)引用的原因、應(yīng)該是因?yàn)锳FN都在作為單例使用叛赚、和self并不互相持有澡绩。

貼一段以前別人帖子里的代碼:
//復(fù)寫setCompletionBlock
- (void)setCompletionBlock:(void (^)(void))block {
    [self.lock lock];
    if (!block) {
        [super setCompletionBlock:nil];
    } else {
        __weak __typeof(self)weakSelf = self;
        [super setCompletionBlock:^ {
            __strong __typeof(weakSelf)strongSelf = weakSelf;

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
            //看有沒(méi)有自定義的完成組,否則用AF的組
            dispatch_group_t group = strongSelf.completionGroup ?: url_request_operation_completion_group();
            //看有沒(méi)有自定義的完成queue俺附,否則用主隊(duì)列
            dispatch_queue_t queue = strongSelf.completionQueue ?: dispatch_get_main_queue();
#pragma clang diagnostic pop
            
            //調(diào)用設(shè)置的Block,在這個(gè)組和隊(duì)列中
            dispatch_group_async(group, queue, ^{
                block();
            });

            //結(jié)束時(shí)候置nil,防止循環(huán)引用
            dispatch_group_notify(group, url_request_operation_completion_queue(), ^{
                [strongSelf setCompletionBlock:nil];
            });
        }];
    }
    [self.lock unlock];
}

  • 把NSURLSession眾多代理轉(zhuǎn)化成了block

這個(gè)說(shuō)實(shí)話我并不太暫停...
個(gè)人感覺(jué)block就是應(yīng)該控制個(gè)數(shù)溪掀、而NSURLSession的代理加起來(lái)起碼有二三十個(gè)事镣。
如果到了這種數(shù)量級(jí)的數(shù)據(jù)傳遞、真的還是用代理吧揪胃、饒了我璃哟。

  • 消除編譯器clang警告

其中Wgnu可以換成其他具體命令

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
#pragma clang diagnostic pop
  • 正則的簡(jiǎn)便寫法

講道理我還真第一次見(jiàn)

`A ?: B = A ? A : B`
  • 如何做到對(duì)外只讀、對(duì)內(nèi)讀寫
.h中
@property (readonly, nonatomic, strong, nullable) NSURL *baseURL;
.m中
@property (readwrite, nonatomic, strong) NSURL *baseURL;

AFNetworkReachabilityManager

AFN中負(fù)責(zé)網(wǎng)絡(luò)狀態(tài)模塊喊递。在不同的網(wǎng)絡(luò)狀態(tài)下可以監(jiān)聽(tīng)随闪、或者實(shí)時(shí)查詢、并且需要手動(dòng)開(kāi)啟或者關(guān)閉骚勘。

  • 四種網(wǎng)絡(luò)狀態(tài)

未知铐伴、無(wú)網(wǎng)絡(luò)撮奏、運(yùn)營(yíng)商網(wǎng)絡(luò)、WiFi網(wǎng)絡(luò)

  • 開(kāi)始暫停
  • 狀態(tài)改變的回調(diào)block

代碼不多当宴、詳情可參閱《iOS源碼補(bǔ)完計(jì)劃--AFNetworking(二)》

知識(shí)點(diǎn)

  • 關(guān)于FOUNDATION_EXPORT和UIKIT_EXTERN的選擇

都可以代替宏來(lái)定義常量

FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityDidChangeNotification;

有人說(shuō)是如果文件基于FOUNDATION則用前者畜吊、反之則用后者。
二者都能替代#define户矢、并且通過(guò)地址比對(duì)常量(也就是可以通過(guò) == 直接進(jìn)行比較)玲献、效率更高。

  • #if - #esle - #endif
#ifdef __IPHONE_11_0
    //對(duì)應(yīng)代碼
#endif

用普通的if-else也是一樣梯浪、好處就是在編譯階段是否會(huì)被編譯捌年。
不過(guò)、#if - #esle - #endif不能用來(lái)判斷一個(gè)動(dòng)態(tài)的語(yǔ)法挂洛。

  • 注冊(cè)鍵值依賴

KVO的一個(gè)冷門方法

+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
    
    if ([key isEqualToString:@"reachable"] || [key isEqualToString:@"reachableViaWWAN"] || [key isEqualToString:@"reachableViaWiFi"]) {
        
        return [NSSet setWithObject:@"networkReachabilityStatus"];
    }

    return [super keyPathsForValuesAffectingValueForKey:key];
}

當(dāng)return的 值被改變的時(shí)候延窜、觸發(fā)key的監(jiān)聽(tīng)
也就是說(shuō)當(dāng)networkReachabilityStatus改變的時(shí)候、reachable/reachableViaWWAN/reachableViaWiFi的KVO監(jiān)聽(tīng)都將被觸發(fā)


AFSecurityPolicy

負(fù)責(zé)網(wǎng)絡(luò)安全策略(證書)的驗(yàn)證模塊

核心代碼

  • .cer文件在iOS里如何使用的

整個(gè)驗(yàn)證都是基于SecTrustRef的抹锄、和.cer文件的關(guān)系大概是:
NSData格式的證書==>SecCertificateRef==>SecTrustRef對(duì)象
SecTrustRef逆瑞、就是一個(gè)內(nèi)部至少攜帶了證書與公鑰的結(jié)構(gòu)體。

  • 三種驗(yàn)證模式

無(wú)條件信任服務(wù)器的證書伙单、對(duì)公鑰驗(yàn)證获高、對(duì)證書驗(yàn)證的具體邏輯。后兩種需要我們本地自建證書(由服務(wù)器提供原始證書生成)吻育。
如果不需要驗(yàn)證什么念秧、壓根不需要設(shè)置AFSecurityPolicy、因?yàn)樵趍anager的初始化里已經(jīng)默認(rèn)了一個(gè)AFSecurityPolicy并且被設(shè)置成無(wú)條件信任服務(wù)器的證書布疼。當(dāng)然摊趾、這樣你的HTTPS除了加密通道意外將毫無(wú)用處、而這個(gè)通道游两、也是可以被抓包的砾层。

其實(shí)整個(gè)模塊也沒(méi)有太多可以研究的地方、因?yàn)槎际枪潭ǖ姆椒浮D阒荒苓@么寫~
不過(guò)肛炮、一行一行看一看。iOS的證書到底是如何驗(yàn)證的宝踪、也不錯(cuò)侨糟。
有興趣可以參閱《iOS源碼補(bǔ)完計(jì)劃--AFNetworking(三)》

知識(shí)點(diǎn)

  • __Require_Quiet判斷

__Require_Quiet__Require_noErr_Quiet
作用其實(shí)和if-esle差不多、但是可以從多個(gè)入口跳到統(tǒng)一的出口瘩燥、相關(guān)函數(shù)__Require_XXX基本都是這個(gè)意思秕重。寫了幾個(gè)小方法、想看的自己可以copy運(yùn)行一下


#import <AssertMacros.h>


    //斷言為假則會(huì)執(zhí)行一下第三個(gè)action厉膀、拋出異常溶耘、并且跳到_out
    __Require_Action(1, _out, NSLog(@"直接跳"));
    //斷言為真則往下二拐、否則跳到_out
    __Require_Quiet(1,_out);
    NSLog(@"111");
    
    //如果不注釋、從這里直接就會(huì)跳到out
//    __Require_Quiet(0,_out);
//    NSLog(@"222");
    
    //如果沒(méi)有錯(cuò)誤汰具、也就是NO卓鹿、繼續(xù)執(zhí)行
    __Require_noErr(NO, _out);
    NSLog(@"333");
    
    //如果有錯(cuò)誤、也就是YES留荔、跳到_out吟孙、并且拋出異常定位
    __Require_noErr(YES, _out);
    NSLog(@"444");
_out:
    NSLog(@"end");

2018-05-17 14:18:12.656703+0800 AFNetWorkingDemo[4046:313255] 111
2018-05-17 14:18:12.656944+0800 AFNetWorkingDemo[4046:313255] 333
AssertMacros: YES == 0 ,  file: /Users/kiritoSong/Desktop/博客/KTAFNetWorkingDemo/AFNetWorkingDemo/AFNetWorkingDemo/ViewController.m, line: 39, value: 1
2018-05-17 14:18:12.657097+0800 AFNetWorkingDemo[4046:313255] end

這樣、我們就有了三種判斷的方式
1聚蝶、普通邏輯的if-else
2杰妓、編譯級(jí)別的#if - #esle - #endif
3、__Require_XXX這種多入口碘勉、統(tǒng)一出口的宏判斷


AFHTTPRequestSerializer

負(fù)責(zé)網(wǎng)絡(luò)請(qǐng)求NSMutableURLRequest對(duì)象的初始化
以及請(qǐng)求頭巷挥、請(qǐng)求體、參數(shù)验靡、上傳文件的自動(dòng)化配置
幾千行代碼倍宾、很長(zhǎng)。但是讀下來(lái)會(huì)受益匪淺胜嗓。

  • 流程圖


    AFHTTPRequestSerializer流程圖

流程看起來(lái)很簡(jiǎn)單高职、但是具體實(shí)施起來(lái)卻有很多東西。
包括如何將參數(shù)字典轉(zhuǎn)化成字符串并且轉(zhuǎn)譯辞州、如何進(jìn)行文件的分段拼接拷貝怔锌、如何將一個(gè)個(gè)請(qǐng)求體文件整合到request中等等。

詳細(xì)的API可以參閱:《iOS源碼補(bǔ)完計(jì)劃--AFNetworking(四)》


AFHTTPResponseSerializer

主要看了看AFURLResponseSerialization的內(nèi)容
負(fù)責(zé)網(wǎng)絡(luò)請(qǐng)求成功之后服務(wù)器返回的響應(yīng)體進(jìn)行格式化

核心代碼

AFURLResponseSerialization協(xié)議以及其解碼方法

- (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response
                           data:(nullable NSData *)data
                          error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;

針對(duì)不同的解析器(JSON/XML/PList等)变过、通過(guò)實(shí)現(xiàn)這個(gè)協(xié)議的方式埃元。
在請(qǐng)求結(jié)束時(shí)、幫助AFURLSessionManager對(duì)獲得的響應(yīng)體進(jìn)行解析媚狰。

詳細(xì)的API可以移步:《iOS源碼補(bǔ)完計(jì)劃--AFNetworking(五)》

知識(shí)點(diǎn)

  • 協(xié)議的應(yīng)用
    • 通過(guò)讓多個(gè)對(duì)象遵循同一份協(xié)議的方式岛杀、可以在解耦的時(shí)候代替繼承、然后重載父類方法時(shí)通用做法哈雏。使得一個(gè)協(xié)議楞件、返回不同的結(jié)果。
    • 在多人協(xié)作的時(shí)候裳瘪、約定好協(xié)議然后交由其他業(yè)務(wù)實(shí)現(xiàn)、也是提升開(kāi)發(fā)效率很普遍的方式罪针。
  • 如何在一個(gè)方法中返回兩個(gè)NSError

可以使用嵌套的方式彭羹、比如NSUnderlyingErrorKey來(lái)指定一個(gè)最主要的錯(cuò)誤。

  • NSIndexSet對(duì)象

NSIndexSet這個(gè)合集泪酱、是NSSet的數(shù)字版派殷。
一個(gè)無(wú)符號(hào)整數(shù)的集合还最、內(nèi)部元素具有唯一性。

NSMutableIndexSet *indexSetM = [NSMutableIndexSet indexSet];
[indexSetM addIndex:19];
[indexSetM addIndex:4];
[indexSetM addIndex:6];
[indexSetM addIndex:8];
[indexSetM addIndexesInRange:NSMakeRange(20, 10)];

[indexSetM enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"%lu",idx);
}];

//2016-08-10 11:39:00.826 qikeyunDemo[3765:100078] 4
//2016-08-10 11:39:00.827 qikeyunDemo[3765:100078] 6
//2016-08-10 11:39:00.827 qikeyunDemo[3765:100078] 8
//2016-08-10 11:39:00.827 qikeyunDemo[3765:100078] 19
//2016-08-10 11:39:00.827 qikeyunDemo[3765:100078] 20
//2016-08-10 11:39:00.828 qikeyunDemo[3765:100078] 21
//2016-08-10 11:39:00.828 qikeyunDemo[3765:100078] 22
//2016-08-10 11:39:00.828 qikeyunDemo[3765:100078] 23
//2016-08-10 11:39:00.828 qikeyunDemo[3765:100078] 24
//2016-08-10 11:39:00.828 qikeyunDemo[3765:100078] 25
//2016-08-10 11:39:00.828 qikeyunDemo[3765:100078] 26
//2016-08-10 11:39:00.828 qikeyunDemo[3765:100078] 27
//2016-08-10 11:39:00.828 qikeyunDemo[3765:100078] 28
//2016-08-10 11:39:00.829 qikeyunDemo[3765:100078] 29

內(nèi)部元素會(huì)自動(dòng)排序

  • 服務(wù)器返回的圖片是壓縮過(guò)的

服務(wù)器返回的圖片毡惜、需要被解壓出bitmap信息拓轻。
bitmap的作用在于在將UIImage交付給UIImageView的時(shí)候。
如果沒(méi)有bitmap將會(huì)在主線程自動(dòng)解壓一次经伙。


最后

本文主要是自己的學(xué)習(xí)與總結(jié)扶叉。如果文內(nèi)存在紕漏、萬(wàn)望留言斧正帕膜。如果不吝賜教小弟更加感謝枣氧。


參考資料

AFNetworking到底做了什么?(終)
iOS源碼補(bǔ)完計(jì)劃--AFNetworking(一)
iOS源碼補(bǔ)完計(jì)劃--AFNetworking(二)
iOS源碼補(bǔ)完計(jì)劃--AFNetworking(三)
iOS源碼補(bǔ)完計(jì)劃--AFNetworking(四)
iOS源碼補(bǔ)完計(jì)劃--AFNetworking(五)
馬在路上----一個(gè)寫了很多源碼解讀的大神

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末垮刹,一起剝皮案震驚了整個(gè)濱河市达吞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荒典,老刑警劉巖酪劫,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異寺董,居然都是意外死亡覆糟,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門螃征,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)搪桂,“玉大人,你說(shuō)我怎么就攤上這事盯滚√咝担” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵魄藕,是天一觀的道長(zhǎng)内列。 經(jīng)常有香客問(wèn)我,道長(zhǎng)背率,這世上最難降的妖魔是什么话瞧? 我笑而不...
    開(kāi)封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮寝姿,結(jié)果婚禮上交排,老公的妹妹穿的比我還像新娘。我一直安慰自己饵筑,他們只是感情好埃篓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著根资,像睡著了一般架专。 火紅的嫁衣襯著肌膚如雪同窘。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天部脚,我揣著相機(jī)與錄音想邦,去河邊找鬼。 笑死委刘,一個(gè)胖子當(dāng)著我的面吹牛丧没,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播钱雷,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼骂铁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了罩抗?” 一聲冷哼從身側(cè)響起拉庵,我...
    開(kāi)封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎套蒂,沒(méi)想到半個(gè)月后钞支,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡操刀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年烁挟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骨坑。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡撼嗓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出欢唾,到底是詐尸還是另有隱情且警,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布礁遣,位于F島的核電站斑芜,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏祟霍。R本人自食惡果不足惜杏头,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望沸呐。 院中可真熱鬧醇王,春花似錦、人聲如沸崭添。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)滥朱。三九已至根暑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間徙邻,已是汗流浹背排嫌。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缰犁,地道東北人淳地。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像帅容,于是被迫代替她去往敵國(guó)和親颇象。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353