ReactiveObjC (二)

参考文档1
参考文档2
参考文档

1.UIKit

监听文本框输入

#UITextField创建了一个 `textSignal`的信号,并订阅了该信号
#当UITextField的内容发生改变时,就会回调subscribeNext

[textField.rac_textSignal subscribeNext:^(id x) {
    self.textLabel.text = x;
}];

RAC(self.textlabel,text) = textField.rac_textSignal;

监听的事件

[[textField rac_signalForControlEvents:UIControlEventEditingChanged] subscribeNext:^(__kindof UIControl * _Nullable x) {

        NSLog(@"点击事件%@",x);
    }];

[[self.red rac_signalForSelector:@selector(touchesBegan:withEvent:)] subscribeNext:^(RACTuple * _Nullable x) {
        
        NSLog(@"控制器知道RedView被点击了");
    }];

2. Interval定时器

程序进入后台,再重新进入前台时,仍然有效,内部是用GCD实现的

#创建一个定时器,间隔1s,在主线程中运行
 @weakify(self)
 
 [[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
      
    @strongify(self)
        
     x.enabled = false;
     self.time = 10;
        
        #RAC中的GCD
        self.dispoable = [[RACSignal interval:1.0 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate * _Nullable x) {

            _time --;
            NSString * title = _time > 0 ? [NSString stringWithFormat:@"请等待 %d 秒后重试",_time] : @"发送验证码";

            [self.btn setTitle:title forState:UIControlStateNormal | UIControlStateDisabled];
         
           self.btn.enabled = (_time==0)? YES : NO;
        
           if (_time == 0) {
                [self.dispoable dispose];
            }
        }];
    }];

3. 遍历


#遍历数组
NSArray *arr = @[@"11",@"3",@"4"];
[arr.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
       NSLog(@"%@",x);
 }];

#遍历字典
NSDictionary *dic = @{@"a":@"1",@"b":@"2"};
[dic.rac_sequence.signal subscribeNext:^(id  _Nullable x) {
      
        NSLog(@"%@",x);

        RACTupleUnpack(NSString *key, NSString *value) = x;
           
         NSLog(@"%@==%@",key,value);
 }];

[dic.rac_keySequence.signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
  }];
[dic.rac_valueSequence.signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
 }];

把集合转换成数组

 NSArray *arr = @[@1,@2,@3,@4,@4];
 NSArray *array = [[arr.rac_sequence map:^id _Nullable(NSNumber * value) {
           
            if (value.integerValue > 2) {
                return @2;
            }else{
                return @3;
            }
        }] array];

4.KVO / 通知

#通知中心

#当dealloc信号发出的时候 就释放通知

[[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidShowNotification object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSNotification * _Nullable x) {
    NSLog(@"%@ 键盘弹起", x); // x 是通知对象
}];

 [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] takeUntil:[self rac_willDeallocSignal]] subscribeNext:^(NSNotification * _Nullable x) {
           NSLog(@"NotificationCenter %@",x);
}];
#方法1
[redView rac_observeKeyPath:@"frame" options:NSKeyValueObservingOptionNew observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
       NSLog(@"%@",value);
 }];

#方法2
[[redView rac_valuesAndChangesForKeyPath:@"center" options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {

       NSLog(@"%@",x);
}];

#方法3
[[redView rac_valuesForKeyPath:@"frame" observer:nil] subscribeNext:^(id  _Nullable x) {
       NSLog(@"%@",x);
  }];

#方法4
[RACObserve(self.view, center) subscribeNext:^(id x) {
  NSLog(@"%@", x);
}];

# 方法1在值发生变化时才执行
# 方法2,3,4 在程序运行时就会被执行

5. RAC 事件绑定

RAC(TARGET, ...)这个宏定义是将对象的属性变化信号与其他信号关联,比如:登录时,当手机号码输入框的文本内容长度为11位时,"发送验证码" 的按钮才可以点击

#当UITextField输入的内容为@"666"时,bView视图的背景颜色变为grayColor

RAC(self.bView, backgroundColor) = [self.textField.rac_textSignal map:^id _Nullable(NSString * _Nullable value) {
    return [value isEqualToString:@"666"]?[UIColor grayColor]:[UIColor orangeColor];
}];


RAC(对象,对象的属性) = (一个信号);

6. rac_liftSelector

当一个界面中有多次请求时,需要保证全部都请求完成,才搭建(刷新)界面,这时需要用到该方法

- (void)rac_liftSelectorTest {
    
    RACSignal *firstSignal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
       
        NSLog(@"模拟第一个网络请求");
        [subscriber sendNext:@"第一次获取到的网络数据"];
        return nil;
    }];
    
    RACSignal *secondSignal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
       
        NSLog(@"模拟第二个网络请求");
        [subscriber sendNext:@"第二次获取到的网络数据"];
        return nil;
    }];
    
    RACSignal *thirdSignal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
       
        NSLog(@"模拟第三个网络请求");
        [subscriber sendNext:@"第三次获取到的网络数据"];
        return nil;
    }];
    
    // 方法updateUIWithData1...的参数,对应每个信号发送的数据
    [self rac_liftSelector:@selector(updateUIWithData1:Data2:Data3:) withSignalsFromArray:@[firstSignal, secondSignal, thirdSignal]];
}

/// 监听多个模块全部执行完成
/// 方法的参数必须与监听的信号一一对应
/// 方法的参数就是每个信号发送的数据
/// @param data1 对应上面firstSignal 监听的信号发送的数据
/// @param data2 对应上面secondSignal 监听的信号发送的数据
/// @param data3 对应上面thirdSignal 监听的信号发送的数据
- (void)updateUIWithData1:(NSString *)data1 Data2:(NSString *)data2 Data3:(NSString *)data3 {
    
    NSLog(@"更新UI:%@-%@-%@", data1, data2, data3);
}

2021-08-19 10:49:55.569808+0800 RAC[22375:2854756] 模拟第一个网络请求
2021-08-19 10:49:55.570144+0800 RAC[22375:2854756] 模拟第二个网络请求
2021-08-19 10:49:55.570290+0800 RAC[22375:2854756] 模拟第三个网络请求
2021-08-19 10:49:55.570463+0800 RAC[22375:2854756] 更新UI:第一次获取到的网络数据-第二次获取到的网络数据-第三次获取到的网络数据

7. RACMulticastConnection

当一个信号被多次订阅,为避免多次调用创建信号中的block,
使用RACMulticastConnection 链接类

RACSignal * signal = 
[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"发送网络请求");
        
        [subscriber sendNext:@"得到网络请求数据"];
        
        return nil;
 }];

RACMulticastConnection *connect = [signal publish];
    
[connect.signal subscribeNext:^(id x) {
        NSLog(@"1 - %@",x);
   }];
    
[connect.signal subscribeNext:^(id x) {
        NSLog(@"2 - %@",x);
  }];
    
 [connect.signal subscribeNext:^(id x) {
        NSLog(@"3 - %@",x);
    }];
 
#注意,最后一定要connect
[connect connect];

6.信号操作

1.串联concat

按一定顺序拼接信号,当多个信号发出的时候,有顺序的接收信号

#创建一个信号管A
  RACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"吃饭"];
        [subscriber sendCompleted];
        return nil;
        
    }];
    
#创建一个信号管B
  RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
       
        [subscriber sendNext:@"吃的饱饱的,才可以睡觉的"];
        [subscriber sendCompleted];
        return nil;
    }];
    
 #串联管A和管B
  RACSignal *concatSiganl = [siganlA concat:siganlB];
   
    #不需要单独订阅signalA,signalB
    #串联后的接收端处理 ,两个事件,走两次,
    #第一个打印siggnalA的结果,
    #第二次打印siganlB的结果
    #第一个信号必须发送完成,第二个信号才会被激活
    [concatSiganl subscribeNext:^(id x) {
        NSLog(@"%@",x);
        
    }];

2021-08-19 10:48:44.780369+0800 RAC[22305:2852537] 吃饭
2021-08-19 10:48:44.780533+0800 RAC[22305:2852537] 吃的饱饱的,才可以睡觉的
2. 并联merge

按顺序合并多个信号为一个信号,其中前一个信号不添加sendCompleted,也会执行后面一个信号。只要有一个信号来,合并操作就会接受。

#创建信号A
RACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"纸厂污水"];
        [subscriber sendCompleted];
        return nil;
    }];
    
#创建信号B
RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
       
        [subscriber sendNext:@"电镀厂污水"];
        [subscriber sendCompleted];
        return nil;
    }];
    
#并联两个信号,根上面一样,分两次打印
RACSignal *mergeSiganl = [RACSignal merge:@[siganlA,siganlB]];
[mergeSiganl subscribeNext:^(id x) {
       
        NSLog(@"%@",x);
        
    }];
    
2021-08-19 14:14:01.471138+0800 RAC[26049:2966473] 纸厂污水
2021-08-19 14:14:01.471334+0800 RAC[26049:2966473] 电镀厂污水
3.combineLatest

将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal至少都有过一次sendNext,才会触发合并的信号。(跟zipWith相似)

reduce: 把信号发出元组的值聚合成一个值

#定义2个自定义信号
RACSubject *letters = [RACSubject subject];
RACSubject *numbers = [RACSubject subject];

#组合信号
[[RACSignal combineLatest:@[letters,numbers]
                   reduce:^(NSString *letter, NSString *number){
        
        return [letter stringByAppendingString:number];
    }] subscribeNext:^(id x) {
        NSLog(@"%@",x);
        
    }];
    
    
    //自己控制发生信号值
    [letters sendNext:@"A"];
    [letters sendNext:@"B"];
    [numbers sendNext:@"1"]; //打印B1
    [letters sendNext:@"C"]; //打印C1
    [numbers sendNext:@"2"];//打印C2
4. zipWith

把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元组,才会触发压缩流的next事件。

  #创建信号A
    RACSignal *siganlA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
       
        [subscriber sendNext:@"红"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    #创建信号B
    RACSignal *siganlB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
       
        [subscriber sendNext:@"白"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    //合流后处理的是压缩包,需要解压后才能取到里面的值
    [[siganlA zipWith:siganlB] subscribeNext:^(id x) {
       
        //解压缩
        RACTupleUnpack(NSString *stringA, NSString *stringB) = x;
        NSLog(@"%@ %@",stringA, stringB);
    }];

5. Map

把源信号的值映射成一个新的值,可以是任意类型的,也可以是信号

  [[_textField.rac_textSignal map:^id(id value) {

        #当源信号发出,就会调用这个block,修改源信号的内容
        #返回值:就是处理完源信号的内容。
        return  [NSString stringWithFormat:@"输出:%@",value];

    }]  subscribeNext:^(id x) {

        NSLog(@"%@",x);
    }];

 RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@"唱歌"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    #对信号进行改进,当信号里面流的是唱歌.就改进为'跳舞'
    RAC(self, tF.text) = [signalA map:^id(NSString *value) {
        if ([value isEqualToString:@"唱歌"]) {
            return @"跳舞";
        }
        return @"";
        
    }];   
6.flattenMap

用于把源信号内容映射成新的内容

RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
            NSLog(@"打蛋液");
            [subscriber sendNext:@"蛋液"];
            [subscriber sendCompleted];
            return nil;
            
        }];
        
 //对信号进行秩序秩序的第一步
signal = [signal flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {

            //处理上一步的RACSiganl的信号value.这里的value=@"蛋液"
            NSLog(@"把%@倒进锅里面煎",value);
            return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
                [subscriber sendNext:@"煎蛋"];
                [subscriber sendCompleted];
                return nil;
            }];
            
        }];
 //对信号进行第二步处理
 signal = [signal flattenMap:^__kindof RACSignal * _Nullable(id  _Nullable value) {
            NSLog(@"把%@装载盘里",value);
            return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
                [subscriber sendNext:@"上菜"];
                [subscriber sendCompleted];
                return nil;
            }];
            
        }];
        
 //最后打印 最后带有===上菜
 [signal subscribeNext:^(id x) {
            NSLog(@"====%@",x);
        }];

7.Then

忽略掉前一个信号发送的值,必须等前一个信号发送sendCompleted表示执行完成后,才执行下一个信号,否则无效,按信号忽略

[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
 
    [subscriber sendNext:@1];
    [subscriber sendCompleted];
    return nil;
}] then:^RACSignal *{
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [subscriber sendNext:@2];
        return nil;
    }];
}] subscribeNext:^(id x) {
  
    NSLog(@"%@",x);
}];

 #只能接收到第二个信号的值,也就是then返回信号的值
8. Filter

对订阅的信号进行筛选

#当UITextField内输入的内容长度大于5时,才会回调subscribeNext

[[[self.textField rac_textSignal] filter:^BOOL(NSString * _Nullable value) {
      return value.length > 5;
}] subscribeNext:^(NSString * _Nullable x) {
      NSLog(@"filter result = %@",  x);
}];

9. Ignore

对订阅的信号进行过滤

[[[self.textField rac_textSignal] ignore:@"666"] subscribeNext:^(NSString * _Nullable x) {

    #当输入的内容 equalTo @"666" 时,这里不执行
    #其他内容,均会执行subscribeNext
    NSLog(@"ignore = %@", x);
}];
10. distinctUntilChanged

当上一次和当前的值不一样,就会发出内容

#在开发中,刷新UI经常使用,只有两次数据不一样才需要刷新
[[_textField.rac_textSignal distinctUntilChanged] subscribeNext:^(id x) {

    NSLog(@"%@",x);
}];

11. take

从开始一共取N次的信号

 // 1、创建信号
    RACSubject *signal = [RACSubject subject];

    // 2、处理信号,订阅信号
    [[signal take:1] subscribeNext:^(id x) {
        
        NSLog(@"%@",x);
    }];

    // 3.发送信号
    [signal sendNext:@1];

    [signal sendNext:@2];

12. takeLast

取最后N次的信号,前提条件,订阅者必须调用完成,因为只有完成,就知道总共有多少信号.

// 1、创建信号
RACSubject *signal = [RACSubject subject];

// 2、处理信号,订阅信号
[[signal takeLast:1] subscribeNext:^(id x) {
    
    NSLog(@"%@",x);
}];

// 3.发送信号
[signal sendNext:@1];

[signal sendNext:@2];

[signal sendCompleted];

13.takeUntil

获取信号直到某个信号执行完成

RACSignal *takeSiganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

       //创建一个定时器信号,每一秒触发一次
        RACSignal *siganl = [RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]];

        [siganl subscribeNext:^(id x) {
           //在这里定时发送next玻璃球
            [subscriber sendNext:@"直到世界尽头"];
            
        }];
        return nil;

    }];

 //创建条件信号
 RACSignal *conditionSiganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

       //设置5s后发生complete
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

            NSLog(@"世界的今天到了,请下车");
            [subscriber sendCompleted];
        });
        return nil;
    }];

 #设置条件,takeSiganl信号在conditionSignal信号接收完成前,不断取值
 [[takeSiganl takeUntil:conditionSiganl] subscribeNext:^(id x) {
        NSLog(@"%@",x);
        
    }];
14. skip

skip:(NSUInteger):跳过几个信号,不接受。

// 表示输入第一次,不会被监听到,跳过第一次发出的信号
[[_textField.rac_textSignal skip:1] subscribeNext:^(id x) {
   
    NSLog(@"%@",x);
}];

15. 延迟
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"等等我,我还有10s就到了");
        [subscriber sendNext:@"北极"];
        [subscriber sendCompleted];
        return nil;
    }];
    
 //延迟10s接受next
 [[siganl delay:10] subscribeNext:^(id x) {
       
        NSLog(@"我到了%@",x);
  
    }];
    // 延时执行
    [[RACScheduler mainThreadScheduler] afterDelay:2 schedule:^{       
        NSLog(@"2秒后执行我");        
    }];

16. 重放

当一个信号被多次订阅,反复播放内容

RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"电影");
        [subscriber sendNext:@"电影"];
        [subscriber sendCompleted];
        return nil;
        
    }];
    
    //创建该普通信号的重复信号
    RACSignal *replaySiganl = [siganl replay];
    //重复接受信号
    [replaySiganl subscribeNext:^(NSString *x) {
        NSLog(@"小米%@",x);
    }];
    [replaySiganl subscribeNext:^(NSString *x) {
        NSLog(@"小红%@",x);
        
    }];
17.定时
    #创建定时器信号.定时8小时  重复发送信号
    RACSignal *siganl = [RACSignal interval:60 * 60 * 8  onScheduler:[RACScheduler mainThreadScheduler]];

    #定时器执行代码
    [siganl subscribeNext:^(id x) {
        NSLog(@"吃药");
        
    }];
18.超时

超时,可以让一个信号在一定的时间后,自动报错。

   RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"我快到了");
        RACSignal *sendSiganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
           
            [subscriber sendNext:nil];
            [subscriber sendCompleted];
            return nil;
        }];
        
        //发生信号要1个小时10分钟才到
        [[sendSiganl delay:60 * 70] subscribeNext:^(id x) {
           //这里才发送next到siganl
            [subscriber sendNext:@"我到了"];
            [subscriber sendCompleted];
            
        }];
        return nil;
        
        
    }];
    
    [[siganl timeout:60 * 60 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) {
       
        NSLog(@"%@",x);
        
    } error:^(NSError * _Nullable error) {
          
          NSLog(@"等了你一个小时,你一直没来,我走了");
      }];
19. 重试

只要失败,就会重新执行创建信号中的block,直到成功

 __block int failedCount = 0;
    
    //创建信号
    RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        if (failedCount < 100) {
            failedCount ++;
            NSLog(@"我失败了");
            [subscriber sendError:nil];
        }else{
            NSLog(@"经历了数百次后,我成功了");
            [subscriber sendNext:nil];

        }
        return nil;
   
    }];
    
    //重试
    RACSignal *retrySiganl = [siganl retry];
    //直到发生next的玻璃球
    [retrySiganl subscribeNext:^(id x) {
        NSLog(@"重要成功了");
        
    }];

20. 节流

当某个信号发送比较频繁时,可以使用节流,在某一段时间不发送信号内容,过了一段时间获取信号的最新内容发出

RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
       //即使发送一个next的Block
        [subscriber sendNext:@"A"];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [subscriber sendNext:@"B"];
            
        });
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [subscriber sendNext:@"C"];
            [subscriber sendNext:@"D"];
            [subscriber sendNext:@"E"];
             
        });
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [subscriber sendNext:@"F"];
        });
        return nil;
        
    }];
    
    //对信号进行节流,限制时间内一次只能通过一个Block
    [[signal throttle:1] subscribeNext:^(id x) {
        NSLog(@"%@通过了",x);
        
    }];
 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容