iOS開發(fā)之ReactiveCocoa的基本用法干貨分享

一诱告、概述

ReactiveCocoa簡(jiǎn)稱RAC精居,基于響應(yīng)式編程思想的Objective-C實(shí)踐靴姿。本文主要結(jié)合代碼示例列舉了RAC的常用類佛吓,常用方法和常用宏辈毯,幫助開發(fā)者快速上手怎樣使用RAC谆沃。

二唁影、常用的類

1据沈、RACSiganl:信號(hào)類锌介,用于傳遞改變的數(shù)據(jù)孔祸,可傳遞以下三種狀態(tài):
  • sendNext:可理解為傳遞正確數(shù)據(jù),告訴訂閱者進(jìn)行下一步處理
  • sendError:傳遞的數(shù)據(jù)錯(cuò)誤拂蝎,告訴訂閱者錯(cuò)誤處理
  • sendCompleted:告訴訂閱者已完成
2温自、RACSubscriber:表示訂閱者的意思悼泌,用于發(fā)送信號(hào)券躁,這是一個(gè)協(xié)議也拜,不是一個(gè)類慢哈,只要遵守這個(gè)協(xié)議卵贱,并且實(shí)現(xiàn)方法才能成為訂閱者。通過(guò)create創(chuàng)建的信號(hào)侣集,都有一個(gè)訂閱者键俱,幫助他發(fā)送數(shù)據(jù)。
  • 沒有訂閱者的 RACSiganl 就是冷信號(hào)世分,相反有訂閱者的 RACSiganl 就是熱信號(hào)编振。為了更好地理解,請(qǐng)參考下圖:


    RAC.png

下面舉個(gè)RAC簡(jiǎn)單用法的栗子:

   //信號(hào)
   RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
      [subscriber sendNext:@"666666"]; //發(fā)送正確數(shù)據(jù)
//      [subscriber sendError:[NSError errorWithDomain:@"xxx" code:1001 userInfo:@{@"errorMessage" : @"錯(cuò)誤"}]]; //發(fā)送錯(cuò)誤
//      [subscriber sendCompleted]; //完成
      return nil;
   }];
   //訂閱者
   [signal subscribeNext:^(id  _Nullable x) {
      NSLog(@"--%@--",x); //接收到數(shù)據(jù)
   } error:^(NSError * _Nullable error) {
      NSLog(@"--%@--",error); //出錯(cuò)處理
   } completed:^{
      NSLog(@"完成"); // 信號(hào)完成
   }];

createSignal 方法block中對(duì)應(yīng)的就是上面說(shuō)的 RACSiganl 傳遞的三種狀態(tài)(sendNext, sendError, sendCompleted)臭埋,subscribeNext就是訂閱方法踪央,對(duì)應(yīng)著 RACSiganl 發(fā)出的三種狀態(tài)做出不同的處理瓢阴。

3畅蹂、RACSubject:既可以充當(dāng)信號(hào),也可以發(fā)送信號(hào)

其實(shí)用法和上面栗子類似:

   RACSubject *subj = [RACSubject subject];
   //訂閱信號(hào)
   [subj subscribeNext:^(id  _Nullable x) {
      NSLog(@"--%@--",x); //接收到數(shù)據(jù)
   } error:^(NSError * _Nullable error) {
      NSLog(@"--%@--",error); //出錯(cuò)處理
   } completed:^{
      NSLog(@"完成"); // 信號(hào)完成
   }];
   //發(fā)送信號(hào)
   [subj sendNext:@"666666"]; //發(fā)送正確數(shù)據(jù)
   //      [subscriber sendError:[NSError errorWithDomain:@"xxx" code:1001 userInfo:@{@"errorMessage" : @"錯(cuò)誤"}]]; //發(fā)送錯(cuò)誤
   //      [subscriber sendCompleted]; //完成

RACSubject的作用通常用來(lái)代替代理荣恐。下面上代碼:

  • 首先創(chuàng)建一個(gè)RedView的類繼承于UIView

RedView.h

#import <UIKit/UIKit.h>
#import <ReactiveObjC/ReactiveObjC.h>

@interface RedView : UIView
@property (nonatomic,strong) RACSubject *subject;
@end

RedView.m

#import "RedView.h"
@implementation RedView

- (RACSubject *)subject {
    if (_subject ==  nil) {
        _subject = [RACSubject subject];
    }
    return _subject;
}

- (IBAction)btnClick:(UIButton *)sender {
    [self.subject sendNext:@"777777"];
}
@end

控制器中代碼:

#import "OrderController.h"
#import <ReactiveObjC/ReactiveObjC.h>
#import "RedView.h"

@interface OrderController ()
@property (weak, nonatomic) IBOutlet RedView *redView;

@end

@implementation OrderController

- (void)viewDidLoad {
   [super viewDidLoad];
   
   [self.redView.subject subscribeNext:^(id  _Nullable x) {
      NSLog(@"--%@--",x); //接收到數(shù)據(jù)
   }];
}

這樣就完成了和代理一樣的功能

4液斜、RACMulticastConnection:信號(hào)連接類

一般情況下,信號(hào)被訂閱多少次叠穆,信號(hào)創(chuàng)建是的block就調(diào)用多少次少漆。但是實(shí)際開發(fā)中,block只需調(diào)用一次就可以了痹束。RACMulticastConnection可以實(shí)現(xiàn)不管訂閱多少次信號(hào)检疫,信號(hào)的block只請(qǐng)求一次:

- (void)viewDidLoad {
   [super viewDidLoad];
   //不管訂閱多少次信號(hào),只請(qǐng)求一次
   //1.創(chuàng)建信號(hào)
   RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
      NSLog(@"請(qǐng)求數(shù)據(jù)");
      [subscriber sendNext:@"請(qǐng)求數(shù)據(jù):777"];
      return nil;
   }];
   //2.把信號(hào)轉(zhuǎn)換成連接類
   RACMulticastConnection * connection = [signal publish];
   //3.訂閱連接類信號(hào)
   [connection.signal subscribeNext:^(id  _Nullable x) {
      NSLog(@"訂閱1:%@",x);
   }];
   [connection.signal subscribeNext:^(id  _Nullable x) {
      NSLog(@"訂閱2:%@",x);
   }];
   [connection.signal subscribeNext:^(id  _Nullable x) {
      NSLog(@"訂閱3:%@",x);
   }];
   //4.連接
   [connection connect];
}

上面的例子中信號(hào)被訂閱了3次祷嘶,但是請(qǐng)求數(shù)據(jù)只請(qǐng)求了1次屎媳。

5、RACCommand:處理事件的類
- (void)viewDidLoad {
   [super viewDidLoad];
   ///1.創(chuàng)建命令
   RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal * _Nonnull(id  _Nullable input) {
      
      /*******此block執(zhí)行命令時(shí)調(diào)用*******/
      //input:對(duì)應(yīng)執(zhí)行命令的參數(shù)论巍,拿到參數(shù)后可以寫處理事件代碼
      NSLog(@"input:%@",input);
      //不能返回空的信號(hào)
      return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
         //傳遞事件產(chǎn)生的數(shù)據(jù)
         [subscriber sendNext:@"執(zhí)行命令產(chǎn)生的數(shù)據(jù)"];
         return nil;
      }];
   }];
   
   ///2.訂閱命令內(nèi)部的信號(hào)
   //方式1:
   //1.執(zhí)行命令
   RACSignal *signal = [command execute:@"666"];
   //2.訂閱信號(hào)
   [signal subscribeNext:^(id  _Nullable x) {
      NSLog(@"~%@~",x);
   }];
   //方式2:(注意:必須在執(zhí)行命令前訂閱信號(hào))
   //1.訂閱信號(hào)
   //executionSignals:信號(hào)源烛谊,信號(hào)中的信號(hào)
   [command.executionSignals subscribeNext:^(id  _Nullable x) {
      [x subscribeNext:^(id  _Nullable x) {
         NSLog(@"~%@~",x);
      }];
   }];
   //2.執(zhí)行命令
   [command execute:@"777"];

   ///3.監(jiān)聽事件有沒有完成
   [command.executing subscribeNext:^(NSNumber * _Nullable x) {
      if ([x boolValue] == YES) {
         NSLog(@"正在執(zhí)行");
      }else {
         NSLog(@"執(zhí)行完成/沒有執(zhí)行");
      }
   }];
}

上面的例子例舉了創(chuàng)建command對(duì)象block中,事件如何處理嘉汰,事件產(chǎn)生的數(shù)據(jù)如何傳遞丹禀。command.executing監(jiān)控事件執(zhí)行的過(guò)程。

三、常用的方法

  • 監(jiān)聽某個(gè)對(duì)象是否調(diào)用某個(gè)方法:
#import "OrderController.h"
#import <ReactiveObjC/ReactiveObjC.h>
#import "RedView.h"
#import "HomeController.h"

@interface OrderController ()
@property (weak, nonatomic) IBOutlet RedView *redView;

@end

@implementation OrderController
- (void)viewDidLoad {
   [super viewDidLoad];
   
   [[self rac_signalForSelector:@selector(push:)] subscribeNext:^(RACTuple * _Nullable x) {
      NSLog(@"跳轉(zhuǎn)");
   }];
}
- (IBAction)push:(id)sender {
   HomeController *vc = [[HomeController alloc] init];
   [self.navigationController pushViewController:vc animated:YES];
}

當(dāng)點(diǎn)擊按鈕調(diào)用 push: 方法時(shí)就會(huì)監(jiān)聽到 push: 方法被調(diào)用了双泪,從而打印出 “跳轉(zhuǎn)”

  • 代替KVO:
#import "OrderController.h"
#import <ReactiveObjC/ReactiveObjC.h>
#import "RedView.h"

@interface OrderController ()
@property (weak, nonatomic) IBOutlet RedView *redView;

@end

@implementation OrderController
- (void)viewDidLoad {
   [super viewDidLoad];
   [[_redView rac_valuesForKeyPath:@"frame" observer:self] subscribeNext:^(id  _Nullable x) {
      //修改的值
      NSLog(@"%@",x);
   }];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
   _redView.frame = CGRectMake(50, 50, 200, 200);
}

上述例子同KVO功能一樣持搜,監(jiān)聽了_redView對(duì)象對(duì)象中的frame屬性,當(dāng)點(diǎn)擊屏幕調(diào)用touchesBegan改變_redView的frame時(shí)焙矛,block里的方法會(huì)被調(diào)用葫盼。

  • 監(jiān)聽事件
[[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
      NSLog(@"按鈕被點(diǎn)擊了");
   }];

給按鈕添加點(diǎn)擊事件

  • 代替通知
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
      NSLog(@"鍵盤被彈出");
   }];

實(shí)現(xiàn)監(jiān)聽鍵盤彈出通知

  • 監(jiān)聽文本框變化
[[self.textField rac_textSignal] subscribeNext:^(NSString * _Nullable x) {
      NSLog(@"UITextField:%@",x);
   }];
  • 所有信號(hào)都返回結(jié)果的時(shí)候,統(tǒng)一做處理
- (void)viewDidLoad {
   [super viewDidLoad];
   //信號(hào)一
   RACSignal *sg1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
      //模擬從服務(wù)器請(qǐng)求數(shù)據(jù)
      [subscriber sendNext:@"請(qǐng)求的數(shù)據(jù)1"]; //請(qǐng)求成功后發(fā)送數(shù)據(jù)
      return nil;
   }];
   //信號(hào)二
   RACSignal *sg2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
      //模擬從服務(wù)器請(qǐng)求數(shù)據(jù)
      [subscriber sendNext:@"請(qǐng)求的數(shù)據(jù)2"]; //請(qǐng)求成功后發(fā)送數(shù)據(jù)
      return nil;
   }];
   //方法upDateUI的參數(shù)村斟,對(duì)應(yīng)每個(gè)信號(hào)發(fā)送的數(shù)據(jù)
   [self rac_liftSelector:@selector(upDateUIWithData1:data2:) withSignalsFromArray:@[sg1,sg2]];
}
- (void)upDateUIWithData1:(NSString *)data1 data2:(NSString *)data2{
   //拿到請(qǐng)求數(shù)據(jù)
   NSLog(@"更新UI:%@--%@",data1,data2);
}

四贫导、常用的宏

  • RAC(xx,xx):給某個(gè)對(duì)象的某個(gè)屬性綁定信號(hào),只要產(chǎn)生信號(hào)內(nèi)容蟆盹,就會(huì)把內(nèi)容給屬性賦值
@interface OrderController ()
@property (weak, nonatomic) IBOutlet UITextField *textField;
@property (weak, nonatomic) IBOutlet UILabel *label;
@end

@implementation OrderController

- (void)viewDidLoad {
   [super viewDidLoad];
   //方法一孩灯,普通方法實(shí)現(xiàn)
   @weakify(self)
   [_textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
      @strongify(self)
      self.label.text = x;
   }];
   //方法二,宏方法實(shí)現(xiàn)
   RAC(_label,text) = _textField.rac_textSignal;
}

上面例子中方法二是利用宏實(shí)現(xiàn)的逾滥,首先將_label的text屬性綁定了_textField的信號(hào)峰档,只要_textField內(nèi)容發(fā)生改變,就會(huì)賦值給_label的text屬性匣距。 例子中兩種方法實(shí)現(xiàn)的效果一樣面哥,用RAC()宏寫更簡(jiǎn)便。

  • RACObserve(_redView, frame):只要對(duì)象屬性改變就會(huì)產(chǎn)生信號(hào)
@interface OrderController ()
@property (weak, nonatomic) IBOutlet RedView *redView;
@end

@implementation OrderController
- (void)viewDidLoad {
   [super viewDidLoad];
   [RACObserve(_redView, frame) subscribeNext:^(id  _Nullable x) {
      //修改的致
      NSLog(@"%@",x);
   }];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
   _redView.frame = CGRectMake(50, 50, 200, 200);
}

與上面說(shuō)的代 替KVO: 舉的例子實(shí)現(xiàn)效果一樣

  • @weakify(self)毅待,@strongify(self):解決RAC中的循環(huán)引用
 @weakify(self)
   [_textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
      @strongify(self)
      self.label.text = x;
   }];

在block外加@weakify(self)方法尚卫,block里面加 @strongify(self)方法,之后只用self.就不會(huì)產(chǎn)生循環(huán)引用尸红。

五吱涉、RAC高級(jí)操作方法

  • bind
    具體操作:給RAC的信號(hào)進(jìn)行綁定,只要信號(hào)已發(fā)送數(shù)據(jù)外里,就能監(jiān)聽到怎爵,從而把數(shù)據(jù)改成自己想要的
- (void)viewDidLoad {
   [super viewDidLoad];
   
   //1.創(chuàng)建信號(hào)
   RACSubject *subj = [RACSubject subject];
   //2.綁定信號(hào)
   RACSignal *bindSignal = [subj bind:^RACSignalBindBlock _Nonnull{
      
      return ^RACSignal *(id value, BOOL *stop) {
         //只要源信號(hào)發(fā)送數(shù)據(jù),就會(huì)調(diào)用此block
         //此block作用:處理源信號(hào)內(nèi)容
         //value:信號(hào)源發(fā)送內(nèi)容
         value = [NSString stringWithFormat:@"orange%@",value];
         NSLog(@"修改后的value:%@",value);
         return [RACReturnSignal return:value];
      };
   }];
   //3.訂閱綁定信號(hào)
   [bindSignal subscribeNext:^(id  _Nullable x) {
      NSLog(@"接收到綁定信號(hào)處理完的信號(hào):%@",x);
   }];
   //4.發(fā)送數(shù)據(jù)
   [subj sendNext:@"888888"];
}

上述例子中盅蝗,發(fā)送的信號(hào)為“888888”鳖链,通過(guò)綁定信號(hào),對(duì)源信號(hào)數(shù)據(jù)進(jìn)行修改墩莫,訂閱后的信號(hào)內(nèi)容就被修改了芙委。

  • 映射
    映射可以把源信號(hào)內(nèi)容更改成新的內(nèi)容
- (void)viewDidLoad {
   [super viewDidLoad];
   //創(chuàng)建信號(hào)
   RACSubject *subj = [RACSubject subject];
   //綁定信號(hào)
   RACSignal *bindSignalX = [subj map:^id _Nullable(id  _Nullable value) {
      //返回的類型就是你需要映射的值
      return [NSString stringWithFormat:@"%d",[value intValue] + 1];
   }];
   //訂閱信號(hào)
   [bindSignalX subscribeNext:^(id  _Nullable x) {
      NSLog(@"%@",x);
   }];
   //發(fā)送數(shù)據(jù)
   [subj sendNext:@"666666"];
}

上述例子中,綁定信號(hào)block中狂秦,將value值+1灌侣,直接return的值就是要映射的值,所以在訂閱信號(hào)中的內(nèi)容就在發(fā)送數(shù)據(jù)基礎(chǔ)上+1裂问。

  • 壓縮信號(hào):所有信號(hào)都發(fā)送內(nèi)容時(shí)侧啼,才會(huì)調(diào)用
    使用場(chǎng)景:當(dāng)一個(gè)界面多個(gè)請(qǐng)求時(shí)牛柒,要等所有請(qǐng)求完成更新UI
- (void)viewDidLoad {
   [super viewDidLoad];
   RACSubject *s1 = [RACSubject subject];
   RACSubject *s2 = [RACSubject subject];
   //壓縮成一個(gè)信號(hào)
   RACSignal *yaS = [s1 zipWith:s2];
   //訂閱信號(hào)
   [yaS subscribeNext:^(id  _Nullable x) {
      NSLog(@"%@",x);
   }];
   //發(fā)送信號(hào)
   [s1 sendNext:@"1"];
   [s2 sendNext:@"2"];
}

上面例子中,當(dāng)s1和s2同時(shí)發(fā)送信號(hào)時(shí)痊乾,訂閱信號(hào)的block才會(huì)調(diào)用皮壁。

  • 組合信號(hào):將兩個(gè)信號(hào)組合,并且可以同時(shí)處理兩個(gè)信號(hào)的內(nèi)容
    使用場(chǎng)景:登錄頁(yè)面賬號(hào)輸入框和密碼輸入框同時(shí)輸入內(nèi)容時(shí)符喝,登錄按鈕才能點(diǎn)擊
@interface HomeController ()
@property (weak, nonatomic) IBOutlet UIButton *btn;
@property (weak, nonatomic) IBOutlet UITextField *textField;
@property (weak, nonatomic) IBOutlet UITextField *textField1;
@end

@implementation HomeController

- (void)viewDidLoad {
    [super viewDidLoad];
    @weakify(self)
    //reduce:聚合的意思,合并兩個(gè)信號(hào)數(shù)據(jù)闪彼,進(jìn)行匯總計(jì)算時(shí)使用的
    RACSignal *signal = [RACSignal combineLatest:@[self.textField.rac_textSignal, self.textField1.rac_textSignal] reduce:^id (NSString *text, NSString *text1){
        //判斷輸入框位數(shù)(需轉(zhuǎn)成NSNumber類型)
        BOOL isHidden;
        if (text.length >= 3 && text1.length >= 6) {
            isHidden = YES;
        }else {
            isHidden = NO;
        }
        return @(isHidden);
    }];
    //訂閱信號(hào)
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"達(dá)成條件返回結(jié)果:%@",x);
        @strongify(self)
        self.btn.hidden = ![x boolValue];
    }];
}

上面例子中甜孤,combineLatest:方法組合了textField和textField1的信號(hào)协饲,reduce的block中是對(duì)兩個(gè)組合信號(hào)的數(shù)據(jù)進(jìn)行計(jì)算并返回計(jì)算后的結(jié)果。通過(guò)訂閱組合后的信號(hào)缴川,就能拿到reduce處理后的解果茉稠,來(lái)判斷登錄按鈕是否顯示。

  • 過(guò)濾
    例1:過(guò)濾掉一些內(nèi)容
[[_textField.rac_textSignal filter:^BOOL(NSString * _Nullable value) {
      //value源信號(hào)內(nèi)容
      //返回值為過(guò)濾的條件
      return [value length] > 5 ; //只有當(dāng)文本框內(nèi)容大于5才能獲取文本框內(nèi)容
   }] subscribeNext:^(NSString * _Nullable x) {
      NSLog(@"大于5時(shí)打印內(nèi)容:%@",x);
   }];

第一個(gè)block中直接返回想要過(guò)濾的條件把夸,只有條件達(dá)成時(shí)而线,訂閱信號(hào)subscribeNext的block內(nèi)的方法才執(zhí)行。

例2:忽略某個(gè)值

   RACSubject *igSub = [RACSubject subject];
   RACSignal *igSignal = [igSub ignore:@"1"];
   [igSignal subscribeNext:^(id  _Nullable x) {
      NSLog(@"%@",x);
   }];
   [igSub sendNext:@"1"];

利用ignore方法設(shè)置要忽略的內(nèi)容:“1”恋日,當(dāng)發(fā)送的消息(sendNext)為“1”時(shí)膀篮,訂閱消息時(shí)就接收不到了。

例3:當(dāng)前值和上一個(gè)值相同就不會(huì)被訂閱
使用場(chǎng)景:當(dāng)模型里一個(gè)屬性沒有變就不會(huì)更新UI界面岂膳,只有不同時(shí)才會(huì)刷新UI

   RACSubject *disSub = [RACSubject subject];
   [[disSub distinctUntilChanged] subscribeNext:^(id  _Nullable x) {
      NSLog(@"%@",x);
   }];
   [disSub sendNext:@"1"];
   [disSub sendNext:@"1"];

兩次發(fā)送的都是“1”誓竿,但是block中只執(zhí)行了一次。

  • 標(biāo)記
    takeUntil需要一個(gè)信號(hào)作為標(biāo)記谈截,當(dāng)標(biāo)記的信號(hào)發(fā)送數(shù)據(jù)筷屡,就停止。
   RACSubject * subject = [RACSubject subject];
   RACSubject * subject1 = [RACSubject subject];
   
   [[subject takeUntil:subject1] subscribeNext:^(id  _Nullable x) {
      NSLog(@"---%@---",x);
   }];
   [subject1 subscribeNext:^(id  _Nullable x) {
      NSLog(@"%@",x);
   }];
   
   [subject sendNext:@"1"];
   [subject sendNext:@"2"];
   [subject sendNext:@"3"];
   
   [subject1 sendNext:@"Stop"];
   
   [subject sendNext:@"4"];
   [subject sendNext:@"5"];

上面例子中subject1信號(hào)發(fā)送數(shù)據(jù)之后簸喂,subject就接收不到4和5了毙死。

  • rac_willDeallocSignal
    對(duì)象銷毀時(shí)發(fā)動(dòng)的信號(hào)
// 監(jiān)聽文本框的改變,直到當(dāng)前對(duì)象被銷毀
[_textField.rac_textSignal takeUntil:self.rac_willDeallocSignal];

以上例子中喻鳄,當(dāng)前對(duì)象被銷毀時(shí)扼倘,會(huì)發(fā)送rac_willDeallocSignal信號(hào),rac_textSignal就停止監(jiān)聽了除呵。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末再菊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子竿奏,更是在濱河造成了極大的恐慌袄简,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泛啸,死亡現(xiàn)場(chǎng)離奇詭異绿语,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門吕粹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)种柑,“玉大人,你說(shuō)我怎么就攤上這事匹耕【矍耄” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵稳其,是天一觀的道長(zhǎng)驶赏。 經(jīng)常有香客問(wèn)我,道長(zhǎng)既鞠,這世上最難降的妖魔是什么煤傍? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮嘱蛋,結(jié)果婚禮上蚯姆,老公的妹妹穿的比我還像新娘。我一直安慰自己洒敏,他們只是感情好龄恋,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凶伙,像睡著了一般郭毕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镊靴,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天铣卡,我揣著相機(jī)與錄音,去河邊找鬼偏竟。 笑死煮落,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的踊谋。 我是一名探鬼主播蝉仇,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼殖蚕!你這毒婦竟也來(lái)了轿衔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤睦疫,失蹤者是張志新(化名)和其女友劉穎害驹,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蛤育,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宛官,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年葫松,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片底洗。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡腋么,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出亥揖,到底是詐尸還是另有隱情珊擂,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布费变,位于F島的核電站摧扇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏胡控。R本人自食惡果不足惜扳剿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望昼激。 院中可真熱鬧,春花似錦锡搜、人聲如沸橙困。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)凡傅。三九已至,卻和暖如春肠缔,著一層夾襖步出監(jiān)牢的瞬間夏跷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工明未, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留槽华,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓趟妥,卻偏偏與公主長(zhǎng)得像猫态,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子披摄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360