iOS ReactiveCocoa學(xué)習(xí)筆記(4):進(jìn)階用法


參考資料:《神奇的RAC宏》

本文知識(shí)點(diǎn):RACMulticastConnection(避免多次請(qǐng)求)、RACCommand(網(wǎng)絡(luò)請(qǐng)求,監(jiān)聽(tīng)命令狀態(tài)厕九,區(qū)別與RACSubject)、RAC常用宏地回。

1. RACMulticastConnection

  • 當(dāng)一個(gè)信號(hào)扁远,被多次訂閱時(shí),為了保證創(chuàng)建信號(hào)時(shí)刻像,避免多次調(diào)用創(chuàng)建信號(hào)中的block畅买,造成副作用,可以使用這個(gè)類(lèi)處理.
  • 注意:RACMulticastConnection通過(guò)RACSignal-publish或者-muticast:方法創(chuàng)建细睡。

1.1 使用步驟

  1. 創(chuàng)建信號(hào) + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe
  2. 創(chuàng)建連接 RACMulticastConnection *connect = [signal publish];
  3. 訂閱信號(hào),注意:訂閱的不再是之前的信號(hào)谷羞,而是connect的信號(hào)。 [connect.signal subscribeNext:nextBlock]
  4. 連接 [connect connect]

1.2 底層原理

  1. 創(chuàng)建connect溜徙,connect.sourceSignal -> RACSignal(原始信號(hào)) connect.signal -> RACSubject
  2. 訂閱connect.signal湃缎,會(huì)調(diào)用RACSubject的subscribeNext,創(chuàng)建訂閱者蠢壹,而且把訂閱者保存起來(lái)嗓违,不會(huì)執(zhí)行block
  3. [connect connect]內(nèi)部會(huì)訂閱RACSignal(原始信號(hào))图贸,并且訂閱者是RACSubject
    1> 訂閱原始信號(hào)蹂季,就會(huì)調(diào)用原始信號(hào)中的didSubscribe
    2> didSubscribe冕广,拿到訂閱者調(diào)用sendNext,其實(shí)是調(diào)用RACSubject的sendNext
  4. RACSubjectsendNext,會(huì)遍歷RACSubject所有訂閱者發(fā)送信號(hào)偿洁。
    1> 因?yàn)閯倓偟诙郊岩ぃ际窃谟嗛?code>RACSubject,因此會(huì)拿到第二步所有的訂閱者父能,調(diào)用他們的nextBlock

1.3 應(yīng)用場(chǎng)景:避免多次請(qǐng)求數(shù)據(jù)

需求:假設(shè)在一個(gè)信號(hào)中發(fā)送請(qǐng)求神凑,每次訂閱一次都會(huì)發(fā)送請(qǐng)求,這樣就會(huì)導(dǎo)致多次請(qǐng)求何吝。
解決:使用RACMulticastConnection就能解決溉委。

// 使用RACSignal出現(xiàn)的情況:多次執(zhí)行nextBlock
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
    static int i = 0;
    i++;
    [subscriber sendNext:@(i)];
    return nil;
}];

[signal subscribeNext:^(id  _Nullable x) {
    NSLog(@"x = %@", x);
}];
[signal subscribeNext:^(id  _Nullable x) {
    NSLog(@"x = %@", x);
}];
[signal subscribeNext:^(id  _Nullable x) {
    NSLog(@"x = %@", x);
}];

Output:
2019-06-14 15:24:32.321216+0800 RacDemo[7221:2430572] x = 1
2019-06-14 15:24:32.321341+0800 RacDemo[7221:2430572] x = 2
2019-06-14 15:24:32.321483+0800 RacDemo[7221:2430572] x = 3


// 解決重復(fù)請(qǐng)求問(wèn)題使用RACMulticastConnection處理:
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
    static int i = 0;
    i++;
    [subscriber sendNext:@(i)];
    return nil;
}];
//創(chuàng)建連接
RACMulticastConnection *connect = [signal publish];
//訂閱信號(hào)
//注意:訂閱信號(hào),也不能激活信號(hào)爱榕,只是保存訂閱者到數(shù)組瓣喊,必須通過(guò)連接,當(dāng)調(diào)用連接,就會(huì)一次性調(diào)用所有訂閱者的sendNext:
[connect.signal subscribeNext:^(id  _Nullable x) {
    NSLog(@"x = %@", x);
}];
[connect.signal subscribeNext:^(id  _Nullable x) {
    NSLog(@"x = %@", x);
}];
[connect.signal subscribeNext:^(id  _Nullable x) {
    NSLog(@"x = %@", x);
}];
//連接,激活信號(hào)(須寫(xiě)在最后)
[connect connect];

Output:
2019-06-14 15:28:44.720282+0800 RacDemo[7224:2431304] x = 1
2019-06-14 15:28:44.720343+0800 RacDemo[7224:2431304] x = 1
2019-06-14 15:28:44.720361+0800 RacDemo[7224:2431304] x = 1

2. RACCommand

  • RAC中用于處理事件的類(lèi)黔酥,可以把事件如何處理,事件中的數(shù)據(jù)如何傳遞藻三,包裝到這個(gè)類(lèi)中,他可以很方便的監(jiān)控事件的執(zhí)行過(guò)程跪者。
  • 監(jiān)聽(tīng)按鈕點(diǎn)擊棵帽,網(wǎng)絡(luò)請(qǐng)求。

2.1 使用步驟

  1. 創(chuàng)建命令 initWithSignalBlock:(RACSignal * (^)(id input))signalBlock
  2. signalBlock中渣玲,創(chuàng)建RACSignal逗概,并且作為signalBlock的返回值
  3. 執(zhí)行命令 - (RACSignal *)execute:(id)input

使用注意:

  1. signalBlock必須要返回一個(gè)信號(hào),不能傳nil.
  2. 如果不想要傳遞信號(hào)忘衍,直接創(chuàng)建空的信號(hào)[RACSignal empty];
  3. RACCommand中信號(hào)如果數(shù)據(jù)傳遞完逾苫,必須調(diào)用[subscriber sendCompleted],這時(shí)命令才會(huì)執(zhí)行完畢枚钓,否則永遠(yuǎn)處于執(zhí)行中铅搓。
    4.buttonrac_commandenbaleSignal不能共存。需要使用帶有enable參數(shù)的方法初始化command搀捷。

2.2 設(shè)計(jì)思想

RACCommand設(shè)計(jì)思想:內(nèi)部signalBlock為什么要返回一個(gè)信號(hào)星掰,這個(gè)信號(hào)有什么用指煎。

  1. 在RAC開(kāi)發(fā)中,通常會(huì)把網(wǎng)絡(luò)請(qǐng)求封裝到RACCommand至壤,直接執(zhí)行某個(gè)RACCommand就能發(fā)送請(qǐng)求。
  2. 當(dāng)RACCommand內(nèi)部請(qǐng)求到數(shù)據(jù)的時(shí)候像街,需要把請(qǐng)求的數(shù)據(jù)傳遞給外界黎棠,這時(shí)候就需要通過(guò)signalBlock返回的信號(hào)傳遞了。

如何拿到RACCommand中返回信號(hào)發(fā)出的數(shù)據(jù):

  1. RACCommand有個(gè)執(zhí)行信號(hào)源executionSignals木西,這個(gè)是signal of signals(信號(hào)的信號(hào)),意思是信號(hào)發(fā)出的數(shù)據(jù)是信號(hào),不是普通的類(lèi)型随静。
  2. 訂閱executionSignals就能拿到RACCommand中返回的信號(hào)八千,然后訂閱signalBlock返回的信號(hào)燎猛,就能獲取發(fā)出的值。

2.3 應(yīng)用場(chǎng)景:監(jiān)聽(tīng)網(wǎng)絡(luò)請(qǐng)求

// 一般采用懶加載的方式
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
    //signalBlock必須要返回一個(gè)信號(hào)沸停,不能傳nil.
    //如果不想要傳遞信號(hào)昭卓,直接創(chuàng)建空的信號(hào)[RACSignal empty];
    return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        //信號(hào)的創(chuàng)建是在主線程中{number = 1, name = main}
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]];
        [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            //NSURLSession自動(dòng)切入子線程申請(qǐng)網(wǎng)絡(luò)請(qǐng)求{number = 5, name = (null)}
            if (error) {
                [subscriber sendError:error];
            } else {
                NSString *dataString = [[NSString alloc] initWithData:data encoding:kCFStringEncodingUTF8];
                [subscriber sendNext:dataString];
                //RACCommand中信號(hào)如果數(shù)據(jù)傳遞完候醒,必須調(diào)用sendCompleted火焰,這時(shí)命令才會(huì)執(zhí)行完畢,否則永遠(yuǎn)處于執(zhí)行中。
                [subscriber sendCompleted];
            }
        }] resume];
        return nil;
    }];
}];

//強(qiáng)引用命令纯赎,不要被銷(xiāo)毀南蹂,否則接收不到數(shù)據(jù)
_command = command;

//command executionSignals是信號(hào)的信號(hào),訂閱它可以拿到signalblock返回的信號(hào)
[[_command executionSignals] subscribeNext:^(id  _Nullable x) {
    //外層信號(hào)是在主線程中創(chuàng)建的晚顷,所以訂閱信號(hào)也是在主線程中{number = 1, name = main}
    NSLog(@"%@" ,x);
    [x subscribeNext:^(id  _Nullable x) {
        //因?yàn)樽顑?nèi)層信號(hào)是在子線程中發(fā)的疗疟,所以也是在子線程中訂閱到這個(gè)信號(hào)的{number = 5, name = (null)}
        NSLog(@"%@", x);
    }];
}];

//或者 RAC的高級(jí)用法 switchToLatest:
//switchToLatest:用于signal of signals策彤,獲取signal of signals發(fā)出的最新信號(hào),也就是可以直接拿到RACCommand中的信號(hào)
[_command.executionSignals.switchToLatest subscribeNext:^(id  _Nullable x) {
    //因?yàn)樽顑?nèi)層信號(hào)是在子線程中發(fā)的匣摘,所以也是在子線程中訂閱到這個(gè)信號(hào)的{number = 5, name = (null)}
    NSLog(@"%@",x);
}];

//要先訂閱信號(hào)音榜,后面再執(zhí)行命令才能收到返回的數(shù)據(jù) !E跗!
[_command execute:@1];

信號(hào)的監(jiān)聽(tīng):
監(jiān)聽(tīng)當(dāng)前命令是否正在執(zhí)行:

//監(jiān)聽(tīng)命令是否執(zhí)行完畢,默認(rèn)會(huì)來(lái)一次嘴办,可以直接跳過(guò)葛家,skip表示跳過(guò)第一次信號(hào)。
[[_command.executing skip:1] subscribeNext:^(NSNumber * _Nullable x) {
    if (x.boolValue) {
        NSLog(@"正在執(zhí)行");
    } else {
        NSLog(@"執(zhí)行完畢");
    }
}];
Output:
正在執(zhí)行
…數(shù)據(jù)…
執(zhí)行完畢

2.4 坑點(diǎn)

2.4.1 rac_command與enable不可同時(shí)存在

button.rac_command已賦值底燎,那么就不能再將button.enbaleSignal綁定:

// 不能同時(shí)存在
btn.rac_command = self.viewModel.loginCommand;
RAC(btn, enabled) = self.viewModel.enableSignal;

解決辦法:使用帶有Enable參數(shù)的api初始化RACComand双仍。

- (instancetype)initWithEnabled:(nullable RACSignal<NSNumber *> *)enabledSignal signalBlock:(RACSignal<ValueType> * (^)(InputType _Nullable input))signalBlock;

btn.rac_command = [[RACCommand alloc] initWithEnabled:self.enableSignal signalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
        return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
            [subscriber sendNext:nil];
            [subscriber sendCompleted];
            return nil;
        }];
    }];

2.4.2 網(wǎng)絡(luò)錯(cuò)誤的獲取

error的獲取并不是使用 command.executionSignals.switchToLatest subscribeError:來(lái)獲取的朱沃∶┯眨可以用兩種方法來(lái)獲取:

  1. 訂閱command.errors
[_command.executionSignals.switchToLatest subscribeNext:^(id  _Nullable x) {
    // success
}];
[_command.errors subscribeNext:^(NSError * _Nullable x) {
    // error 
}];
  1. 訂閱[command execute:]
@weakify(self);
[[Btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
    @strongify(self);
    [[self.viewModel.command execute:nil] subscribeNext:^(id  _Nullable x) {
        // success    
    } error:^(NSError * _Nullable error) {
        // error    
    }];
}];

2.5 與RACSubject區(qū)別

RACSubject較為靈活翎卓,建議少用失暴,通常用來(lái)代替delegate微饥。
區(qū)別用計(jì)算機(jī)網(wǎng)絡(luò)中的術(shù)語(yǔ)來(lái)講:RACSubject更像“單工”欠橘,而RACCommand就類(lèi)似于“半雙工”。

RACSubject只能單向發(fā)送事件蛮拔,發(fā)送者將事件發(fā)送出去讓接收者接收事件后進(jìn)行處理,所以畦韭,RACSubject可代替代理肛跌,被監(jiān)聽(tīng)者可利用subject發(fā)送事件衍慎,監(jiān)聽(tīng)者接收事件然后進(jìn)行相應(yīng)的監(jiān)聽(tīng)處理,不過(guò)赠法,事件的傳遞方向是單向的乔夯。

對(duì)于RACCommand末荐,用HTTP請(qǐng)求能夠更形象地說(shuō)明其原理,HTTP請(qǐng)求是由請(qǐng)求者向服務(wù)器發(fā)送一條網(wǎng)絡(luò)請(qǐng)求眶熬,而服務(wù)器接收到請(qǐng)求然后經(jīng)過(guò)相應(yīng)處理后再向請(qǐng)求者返回處理過(guò)后的結(jié)果块请,數(shù)據(jù)流是雙向的墩新,RACCommand正是如此。當(dāng)我想讓某個(gè)部件進(jìn)行某種會(huì)產(chǎn)生結(jié)果的操作時(shí),利用RACCommand向此部件發(fā)送執(zhí)行事件狸涌,部件接收到執(zhí)行事件后進(jìn)行相應(yīng)操作處理并也通過(guò)RACCommand將操作結(jié)果回調(diào)到上層帕胆,使得事件得以雙向流通。
以上的解釋是建立在RACCommand的事件產(chǎn)生與接收者為同一個(gè)對(duì)象的前提下的芙盘,而RACCommand也能將事件產(chǎn)生者和訂閱者分離儒老,讓某個(gè)對(duì)象專(zhuān)門(mén)發(fā)送事件,通過(guò)RACCommand將事件傳遞到對(duì)數(shù)據(jù)進(jìn)行操作處理的對(duì)象薇正,最后囚衔,當(dāng)數(shù)據(jù)處理完后再搭載著RACCommand把結(jié)果事件傳出來(lái)练湿,并被訂閱者對(duì)象訂閱。

下面的這張圖表明了我對(duì)RACSubject與RACCommand的理解:



3. 常見(jiàn)宏

3.1 RAC()

RAC(TARGET, [KEYPATH, [NIL_VALUE]])

  • 這個(gè)宏是最常用的辽俗,RAC()總是出現(xiàn)在等號(hào)左邊榆苞,等號(hào)右邊是一個(gè)RACSignal霞捡,表示的意義是將一個(gè)對(duì)象的一個(gè)屬性和一個(gè)signal綁定。
  • signal每產(chǎn)生一個(gè)value(id類(lèi)型)赊琳,都會(huì)自動(dòng)執(zhí)行 [TARGET setValue:value ?: NIL_VALUE forKeyPath:KEYPATH] 躏筏。
  • 數(shù)字值會(huì)升級(jí)為NSNumber *呈枉,當(dāng)setValue:forKeyPath時(shí)會(huì)自動(dòng)降級(jí)成基本類(lèi)型(int, float ,BOOL等)猖辫,所以RAC綁定一個(gè)基本類(lèi)型的值是沒(méi)有問(wèn)題的。宏定義如下:
#define RAC(TARGET, ...) \
    metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__)) \
        (RAC_(TARGET, __VA_ARGS__, nil)) \
        (RAC_(TARGET, __VA_ARGS__))

應(yīng)用場(chǎng)景:


只要文本框文字改變芝囤,就會(huì)修改 label 的文字
//Ex:只要文本框文字改變悯姊,就會(huì)修改 label 的文字
RAC(_label, text) = _textField.rac_textSignal;

//Ex:監(jiān)聽(tīng)兩個(gè)文本框的內(nèi)容,有內(nèi)容才允許按鈕點(diǎn)擊
RAC(_login_btn, enabled) = [RACSignal combineLatest:@[_usernama_tf.rac_textSignal, _pwd_tf.rac_textSignal] reduce:^id _Nonnull (NSString *userName, NSString *pwd){
    return @(userName.length > 0 && pwd.length > 0);
}];

3.2 RACObeserve()

RACObserve(TARGET, KEYPATH)

  • 作用是觀察TARGET的KEYPATH屬性仆嗦,相當(dāng)于KVO岸晦,產(chǎn)生一個(gè)RACSignal启上。最常用的使用,和RAC宏綁定屬性倒慧。宏定義如下:
#define _RACObserve(TARGET, KEYPATH) \
({ \
    __weak id target_ = (TARGET); \
    [target_ rac_valuesForKeyPath:@keypath(TARGET, KEYPATH) observer:self]; \
})
#if __clang__ && (__clang_major__ >= 8)
#define RACObserve(TARGET, KEYPATH) _RACObserve(TARGET, KEYPATH)
#else
#define RACObserve(TARGET, KEYPATH) \
({ \
    _Pragma("clang diagnostic push") \
    _Pragma("clang diagnostic ignored \"-Wreceiver-is-weak\"") \
    _RACObserve(TARGET, KEYPATH) \
    _Pragma("clang diagnostic pop") \
})
#endif

應(yīng)用場(chǎng)景:雙向綁定

1> Model -> UI  RAC(TARGET, ...) = RACObserve(TARGET, KEYPATH);
//如果使用基本數(shù)據(jù)類(lèi)型綁定UI內(nèi)容纫谅,需要使用map函數(shù)溅固,通過(guò)block對(duì)value的數(shù)值進(jìn)行轉(zhuǎn)換后才能夠綁定侍郭。
RAC(name_textField, text) = RACObserve(_person, name);
//rac中傳遞的數(shù)據(jù)都是id類(lèi)型,如果是基本類(lèi)型猛计,需要使用map函數(shù)爆捞,通過(guò)block對(duì)value的數(shù)值進(jìn)行轉(zhuǎn)換后才能夠綁定煮甥。
RAC(age_textField, text) = [RACObserve(_person, age) map:^id _Nullable(id  _Nullable value) {
    return [value description];
}];
2> UI -> Model
@weakify(self);
[[RACSignal combineLatest:@[[name_tf rac_textSignal], [age_tf rac_textSignal]]] subscribeNext:^(RACTuple * _Nullable x) {
    @strongify(self);
    self.person.name = x.first;
    self.person.age = [x.second integerValue];
}];

3.3 RACTuplePack

把數(shù)據(jù)包裝成RACTuple。宏定義如下:

#define RACTuplePack(...) \
    RACTuplePack_(__VA_ARGS__)
#define RACTuplePack_(...) \
    ([RACTuplePack_class_name(__VA_ARGS__) tupleWithObjectsFromArray:@[ metamacro_foreach(RACTuplePack_object_or_ractuplenil,, __VA_ARGS__) ]])

應(yīng)用場(chǎng)景:

RACTuple *tuple = RACTuplePack(@1, @2);

3.4 RACTupleUnpack

RACTuple(元組類(lèi))解包成對(duì)應(yīng)的數(shù)據(jù)肌访。按順序給對(duì)象賦值:如果對(duì)象數(shù)量多于元祖內(nèi)對(duì)象數(shù),后面不賦值店煞。宏定義如下:

#define RACTupleUnpack(...) \
        RACTupleUnpack_(__VA_ARGS__)
#define RACTupleUnpack_(...) \
    metamacro_foreach(RACTupleUnpack_decl,, __VA_ARGS__) \
    \
    int RACTupleUnpack_state = 0; \
    \
    RACTupleUnpack_after: \
        ; \
        metamacro_foreach(RACTupleUnpack_assign,, __VA_ARGS__) \
        if (RACTupleUnpack_state != 0) RACTupleUnpack_state = 2; \
        \
        while (RACTupleUnpack_state != 2) \
            if (RACTupleUnpack_state == 1) { \
                goto RACTupleUnpack_after; \
            } else \
                for (; RACTupleUnpack_state != 1; RACTupleUnpack_state = 1) \
                    [RACTupleUnpackingTrampoline trampoline][ @[ metamacro_foreach(RACTupleUnpack_value,, __VA_ARGS__) ] ]

應(yīng)用場(chǎng)景:

RACTuple *tuple = RACTuplePack(@1, @2);
RACTupleUnpack(NSString *title1, NSString *title2, NSString *title3) = tuple;
NSLog(@"%@, %@, %@", title1, title2, title3);

Output:
2018-04-05 14:33:58.859491+0800 RACDemo[12628:374427] 1, 2, (null)

3.5 weakify顷蟀、strongify

@weakify(obj)、@strongify(obj)

一般配套使用羞反,解決引用循環(huán)囤萤。因?yàn)橄到y(tǒng)提供的信號(hào)是始終存在的涛舍,因此在RAC中所有的block中,如果出現(xiàn)self/成員變量掸驱,幾乎百分之百會(huì)循環(huán)引用没佑。
應(yīng)用場(chǎng)景:

@weakify(self); // 定義了一個(gè)__weak的self_weak_變量 
[RACObserve(self, name) subscribeNext:^(NSString *name) { 
    @strongify(self); // 局域定義了一個(gè)__strong的self指針指向self_weak 
    self.outputLabel.text = name; 
}]; 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蛤奢,一起剝皮案震驚了整個(gè)濱河市远剩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌锥余,老刑警劉巖痢掠,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件足画,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡医舆,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)霞怀,“玉大人毙石,你說(shuō)我怎么就攤上這事≈褪保” “怎么了丧蘸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵力喷,是天一觀的道長(zhǎng)弟孟。 經(jīng)常有香客問(wèn)我,道長(zhǎng)庭猩,這世上最難降的妖魔是什么陈症? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任录肯,我火速辦了婚禮,結(jié)果婚禮上优炬,老公的妹妹穿的比我還像新娘厅贪。我一直安慰自己养涮,他們只是感情好眉抬,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布吐辙。 她就那樣靜靜地躺著,像睡著了一般尊沸。 火紅的嫁衣襯著肌膚如雪洼专。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,475評(píng)論 1 312
  • 那天烟很,我揣著相機(jī)與錄音雾袱,去河邊找鬼官还。 笑死望伦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的腿箩。 我是一名探鬼主播劣摇,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼饵撑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了垢乙?” 一聲冷哼從身側(cè)響起语卤,我...
    開(kāi)封第一講書(shū)人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎骂倘,沒(méi)想到半個(gè)月后巴席,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體漾唉,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赵刑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年般此,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邀桑。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡概漱,死狀恐怖喜喂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情照弥,我是刑警寧澤进副,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布影斑,位于F島的核電站矫户,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏柑蛇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盆耽。 院中可真熱鬧摄杂,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)振劳。三九已至,卻和暖如春寸癌,著一層夾襖步出監(jiān)牢的瞬間弱贼,已是汗流浹背吮旅。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工庇勃, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人责嚷。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓再层,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蒿秦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子棍鳖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容