RAC详细解析(二)—— 基础使用方法

版本记录

版本号 时间
V1.0 2017.08.07

前言

RAC可以简化很多我们的代码,具有很大的天然优势,还是要学一学的,我接下来这几篇就从ReactiveCocoa的基础到深入和大家说一下RAC的使用方法,希望对自己对大家有所帮助。感兴趣的可以看我上面写的这篇。
1. RAC详细解析(一)—— 框架概览

基本使用方法

这一篇就说一下几种主要的使用方法,都是很基础的使用。

1. Target - Action响应的使用

这种目标-动作模式可以用RAC来实现。

系统UIButton响应事件

#import "JJRACUseVC.h"
#import "Masonry.h"
#import "ReactiveCocoa/ReactiveCocoa.h"

@interface JJRACUseVC ()

@end

@implementation JJRACUseVC

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"RAC的基本使用";
    self.view.backgroundColor = [UIColor lightTextColor];
    
    [self loadOriginalButton];
}

#pragma mark - Object Private Function

- (void)loadOriginalButton
{
    UIButton *startButton = [UIButton buttonWithType:UIButtonTypeCustom];
    startButton.backgroundColor = [UIColor lightTextColor];
    [startButton setTitle:@"开始" forState:UIControlStateNormal];
    startButton.titleLabel.font = [UIFont boldSystemFontOfSize:25.0];
    [startButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [startButton addTarget:self action:@selector(startButtonDidClick:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:startButton];
    
    [startButton sizeToFit];
    [startButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self.view);
    }];
}

#pragma mark - Action && Notification

- (void)startButtonDidClick:(UIButton *)button
{
    NSLog(@"被点击了");
}

@end

看结果输出

2017-08-07 15:23:27.646651+0800 JJOC[8093:3264727] 被点击了
2017-08-07 15:23:27.929708+0800 JJOC[8093:3264727] 被点击了

RAC改造后UIButton响应事件

#import "JJRACUseVC.h"
#import "Masonry.h"
#import "ReactiveCocoa/ReactiveCocoa.h"

@interface JJRACUseVC ()

@end

@implementation JJRACUseVC

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"RAC的基本使用";
    self.view.backgroundColor = [UIColor lightTextColor];
    
    [self loadOriginalButton];
}

#pragma mark - Object Private Function

- (void)loadOriginalButton
{
    UIButton *startButton = [UIButton buttonWithType:UIButtonTypeCustom];
    startButton.backgroundColor = [UIColor lightTextColor];
    [startButton setTitle:@"开始" forState:UIControlStateNormal];
    startButton.titleLabel.font = [UIFont boldSystemFontOfSize:25.0];
    [startButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:startButton];
    
    [startButton sizeToFit];
    [startButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self.view);
    }];
    
    [[startButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
        NSLog(@"RAC被点击了");
    }];
}
@end

看一下结果输出

2017-08-07 15:28:06.119778+0800 JJOC[8096:3265805] RAC被点击了

从上面可以看到,系统的给按钮添加响应的方法

[startButton addTarget:self action:@selector(startButtonDidClick:) forControlEvents:UIControlEventTouchUpInside];

- (void)startButtonDidClick:(UIButton *)button
{
    NSLog(@"被点击了");
}

被RAC中下面的方法取代了。

 [[startButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
        NSLog(@"RAC被点击了");
    }];

这样有一个优点就是代码更简洁和集中。

除了UIButtonUITextField也可以这么使用和改造。

下面我们接着看一下点击手势UITapGestureRecognizer方面RAC的应用。

系统UITapGestureRecognizer手势

#import "JJRACUseVC.h"
#import "Masonry.h"
#import "ReactiveCocoa/ReactiveCocoa.h"

@interface JJRACUseVC ()

@end

@implementation JJRACUseVC

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"RAC的基本使用";
    self.view.backgroundColor = [UIColor lightTextColor];

    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gestureDidTapped:)];
    [self.view addGestureRecognizer:tapGesture];
}

#pragma mark - Action && Notification

- (void)gestureDidTapped:(UITapGestureRecognizer *)tapGesture
{
    NSLog(@"点击手势");
}
@end

看结果输出

2017-08-07 15:49:45.122845+0800 JJOC[8100:3269324] 点击手势

RAC改造手势UITapGestureRecognizer

#import "JJRACUseVC.h"
#import "Masonry.h"
#import "ReactiveCocoa/ReactiveCocoa.h"

@interface JJRACUseVC ()

@end

@implementation JJRACUseVC

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"RAC的基本使用";
    self.view.backgroundColor = [UIColor lightTextColor];

    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] init];
    [[tapGesture rac_gestureSignal] subscribeNext:^(id x) {
        NSLog(@"点击手势");
    }];
    [self.view addGestureRecognizer:tapGesture];
}
@end

下面看输出结果

2017-08-07 15:52:44.342459+0800 JJOC[8105:3270075] 点击手势

2. 通知 - NSNotification

通知是我们总用的一种通信机制,RAC中也可以对通知进行改造,下面我们先看一下系统的通知。

系统通知NSNotification

1. JJRACNotificationAddVC.m
#import "JJRACNotificationAddVC.h"
#import "ReactiveCocoa/ReactiveCocoa.h"
#import "JJRACNotificationPostVC.h"

@interface JJRACNotificationAddVC ()

@end

@implementation JJRACNotificationAddVC

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"RAC的基本使用";
    self.view.backgroundColor = [UIColor lightTextColor];

    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] init];
    [[tapGesture rac_gestureSignal] subscribeNext:^(id x) {
        JJRACNotificationPostVC *postVC = [[JJRACNotificationPostVC alloc] init];
        [self.navigationController pushViewController:postVC animated:YES];
    }];
    [self.view addGestureRecognizer:tapGesture];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveNotification:) name:@"notification" object:nil];
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - Action && Notification

- (void)didReceiveNotification:(NSNotification *)noti
{
    NSLog(@"收到通知了");
}

@end
2. JJRACNotificationPostVC.m
#import "JJRACNotificationPostVC.h"

@interface JJRACNotificationPostVC ()

@end

@implementation JJRACNotificationPostVC

- (void)viewDidLoad
{
    [super viewDidLoad];
   
    [[NSNotificationCenter defaultCenter] postNotificationName:@"notification" object:nil userInfo:nil];
}

@end

下面看输出结果

2017-08-07 16:04:31.352838+0800 JJOC[8108:3271268] 收到通知了
2017-08-07 16:04:46.500606+0800 JJOC[8108:3271268] 收到通知了

RAC改造通知NSNotification

#import "JJRACNotificationAddVC.h"
#import "ReactiveCocoa/ReactiveCocoa.h"
#import "JJRACNotificationPostVC.h"

@interface JJRACNotificationAddVC ()

@end

@implementation JJRACNotificationAddVC

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"RAC的基本使用";
    self.view.backgroundColor = [UIColor lightTextColor];

    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] init];
    [[tapGesture rac_gestureSignal] subscribeNext:^(id x) {
        JJRACNotificationPostVC *postVC = [[JJRACNotificationPostVC alloc] init];
        [self.navigationController pushViewController:postVC animated:YES];
    }];
    [self.view addGestureRecognizer:tapGesture];

    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"notification" object:nil] subscribeNext:^(id x) {
        NSLog(@"收到通知了");
    }];
}
@end

看输出结果

2017-08-07 16:08:02.155427+0800 JJOC[8111:3271927] 收到通知了

注意RAC中的通知不需要remove observer,因为在rac_addObserverForName方法中他已经写了remove

3. 键值观察 - KVO

系统键值观察KVO

下面直接看代码。

#import "JJRACKVOVC.h"

@interface JJRACKVOVC ()

@property (nonatomic, strong) UITableView *tableView;

@end

@implementation JJRACKVOVC

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"KVO键值观察";
    
    self.view.backgroundColor = [UIColor lightTextColor];
    
    [self setupUI];
}

- (void)dealloc
{
    [self.tableView removeObserver:self forKeyPath:@"contentOffset"];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    if (object == self.tableView && [keyPath isEqualToString:@"contentOffset"]) {
        NSLog(@"%f~~%f",self.tableView.contentOffset.x,self.tableView.contentOffset.y);
        NSLog(@"%@",change[NSKeyValueChangeNewKey]);
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

#pragma mark - Object Private Function

- (void)setupUI
{
    UITableView *tableView  = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
    tableView.contentSize = CGSizeMake(2000, 2000);
    [self.view addSubview:tableView];
    self.tableView = tableView;
    
    [self.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
}

@end

下面看输出结果

2017-08-07 16:40:49.452546+0800 JJOC[8122:3275485] 0.000000~~-59.000000
2017-08-07 16:40:49.452850+0800 JJOC[8122:3275485] NSPoint: {0, -59}
2017-08-07 16:40:49.469207+0800 JJOC[8122:3275485] 0.000000~~-59.500000
2017-08-07 16:40:49.469515+0800 JJOC[8122:3275485] NSPoint: {0, -59.5}
2017-08-07 16:40:49.486055+0800 JJOC[8122:3275485] 0.000000~~-60.500000
2017-08-07 16:40:49.486352+0800 JJOC[8122:3275485] NSPoint: {0, -60.5}
2017-08-07 16:40:49.502573+0800 JJOC[8122:3275485] 0.000000~~-61.000000
2017-08-07 16:40:49.502872+0800 JJOC[8122:3275485] NSPoint: {0, -61}

这里面还有几个常量需要简单说明一下。

首先是[self.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]里面的枚举NSKeyValueObservingOptions

enum {
    // 提供属性的新值
    NSKeyValueObservingOptionNew = 0x01,
    
    // 提供属性的旧值
    NSKeyValueObservingOptionOld = 0x02,
    
    // 如果指定,则在添加观察者的时候立即发送一个通知给观察者,
    // 并且是在注册观察者方法返回之前
    NSKeyValueObservingOptionInitial = 0x04,
    
    // 如果指定,则在每次修改属性时,会在修改通知被发送之前预先发送一条通知给观察者,
    // 这与-willChangeValueForKey:被触发的时间是相对应的。
    // 这样,在每次修改属性时,实际上是会发送两条通知。
    NSKeyValueObservingOptionPrior = 0x08
};
typedef NSUInteger NSKeyValueObservingOptions;

然后是- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)contextchange字典中的键。

// 属性变化的类型,是一个NSNumber对象,包含NSKeyValueChange枚举相关的值
NSString *const NSKeyValueChangeKindKey;

// 属性的新值。当NSKeyValueChangeKindKey是 NSKeyValueChangeSetting,
// 且添加观察的方法设置了NSKeyValueObservingOptionNew时,我们能获取到属性的新值。
// 如果NSKeyValueChangeKindKey是NSKeyValueChangeInsertion或者NSKeyValueChangeReplacement,
// 且指定了NSKeyValueObservingOptionNew时,则我们能获取到一个NSArray对象,包含被插入的对象或
// 用于替换其它对象的对象。
NSString *const NSKeyValueChangeNewKey;

// 属性的旧值。当NSKeyValueChangeKindKey是 NSKeyValueChangeSetting,
// 且添加观察的方法设置了NSKeyValueObservingOptionOld时,我们能获取到属性的旧值。
// 如果NSKeyValueChangeKindKey是NSKeyValueChangeRemoval或者NSKeyValueChangeReplacement,
// 且指定了NSKeyValueObservingOptionOld时,则我们能获取到一个NSArray对象,包含被移除的对象或
// 被替换的对象。
NSString *const NSKeyValueChangeOldKey;

// 如果NSKeyValueChangeKindKey的值是NSKeyValueChangeInsertion、NSKeyValueChangeRemoval
// 或者NSKeyValueChangeReplacement,则这个key对应的值是一个NSIndexSet对象,
// 包含了被插入、移除或替换的对象的索引
NSString *const NSKeyValueChangeIndexesKey;

// 当指定了NSKeyValueObservingOptionPrior选项时,在属性被修改的通知发送前,
// 会先发送一条通知给观察者。我们可以使用NSKeyValueChangeNotificationIsPriorKey
// 来获取到通知是否是预先发送的,如果是,获取到的值总是@(YES)
NSString *const NSKeyValueChangeNotificationIsPriorKey;

这里面NSKeyValueChangeKindKey是由如下的枚举定义的。

/* Possible values in the NSKeyValueChangeKindKey entry in change dictionaries. See the comments for -observeValueForKeyPath:ofObject:change:context: for more information.
*/
typedef NS_ENUM(NSUInteger, NSKeyValueChange) {
    NSKeyValueChangeSetting = 1,
    NSKeyValueChangeInsertion = 2,
    NSKeyValueChangeRemoval = 3,
    NSKeyValueChangeReplacement = 4,
};

RAC改造后键值观察KVO


#import "JJRACKVOVC.h"
#import "ReactiveCocoa/ReactiveCocoa.h"

@interface JJRACKVOVC ()

@property (nonatomic, strong) UITableView *tableView;

@end

@implementation JJRACKVOVC

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"KVO键值观察";
    
    self.view.backgroundColor = [UIColor lightTextColor];
    
    [self setupUI];
}

#pragma mark - Object Private Function

- (void)setupUI
{
    UITableView *tableView  = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
    tableView.contentSize = CGSizeMake(2000, 2000);
    [self.view addSubview:tableView];
    self.tableView = tableView;
    
    [RACObserve(self.tableView, contentOffset) subscribeNext:^(id x) {
        NSLog(@"%f~~%f",self.tableView.contentOffset.x,self.tableView.contentOffset.y);
    }];
}

@end

下面看输出结果

2017-08-07 16:54:53.739141+0800 JJOC[8129:3279063] 0.000000~~-56.500000
2017-08-07 16:54:53.759018+0800 JJOC[8129:3279063] 0.000000~~-57.500000
2017-08-07 16:54:53.775475+0800 JJOC[8129:3279063] 0.000000~~-58.500000
2017-08-07 16:54:53.792334+0800 JJOC[8129:3279063] 0.000000~~-59.000000
2017-08-07 16:54:53.808930+0800 JJOC[8129:3279063] 0.000000~~-60.000000
2017-08-07 16:54:53.825839+0800 JJOC[8129:3279063] 0.000000~~-60.500000
2017-08-07 16:54:53.842181+0800 JJOC[8129:3279063] 0.000000~~-61.000000
2017-08-07 16:54:53.859100+0800 JJOC[8129:3279063] 0.000000~~-61.500000
2017-08-07 16:54:53.875383+0800 JJOC[8129:3279063] 0.000000~~-61.500000
2017-08-07 16:54:53.889271+0800 JJOC[8129:3279063] 0.000000~~-62.000000
2017-08-07 16:54:53.908936+0800 JJOC[8129:3279063] 0.000000~~-62.500000
2017-08-07 16:54:53.925394+0800 JJOC[8129:3279063] 0.000000~~-62.500000
2017-08-07 16:54:53.938987+0800 JJOC[8129:3279063] 0.000000~~-62.500000
2017-08-07 16:54:53.955523+0800 JJOC[8129:3279063] 0.000000~~-63.000000
2017-08-07 16:54:53.974787+0800 JJOC[8129:3279063] 0.000000~~-63.000000
2017-08-07 16:54:53.989017+0800 JJOC[8129:3279063] 0.000000~~-63.000000

4. 代理 - delegate

系统代理实现 - delegate

#import "JJRACDelegateVC.h"

@interface JJRACDelegateVC () <UIScrollViewDelegate>

@property (nonatomic, strong) UITableView *tableView;

@end

@implementation JJRACDelegateVC

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"代理RAC";
    
    self.view.backgroundColor = [UIColor lightTextColor];
    
    [self setupUI];
}

#pragma mark - Object Private Function'

- (void)setupUI
{
    UITableView *tableView  = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
    tableView.contentSize = CGSizeMake(2000, 2000);
    tableView.delegate = self;
    [self.view addSubview:tableView];
    self.tableView = tableView;
}

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSLog(@"%f~~%f",scrollView.contentOffset.x,scrollView.contentOffset.y);
}

@end

看一下输出结果

2017-08-07 17:01:03.688621+0800 JJOC[8132:3279828] 0.000000~~-43.000000
2017-08-07 17:01:03.705258+0800 JJOC[8132:3279828] 0.000000~~-46.500000
2017-08-07 17:01:03.721466+0800 JJOC[8132:3279828] 0.000000~~-49.000000
2017-08-07 17:01:03.738735+0800 JJOC[8132:3279828] 0.000000~~-51.500000
2017-08-07 17:01:03.754964+0800 JJOC[8132:3279828] 0.000000~~-53.500000
2017-08-07 17:01:03.771588+0800 JJOC[8132:3279828] 0.000000~~-55.000000
2017-08-07 17:01:03.784926+0800 JJOC[8132:3279828] 0.000000~~-56.500000
2017-08-07 17:01:03.801667+0800 JJOC[8132:3279828] 0.000000~~-57.500000
2017-08-07 17:01:03.818327+0800 JJOC[8132:3279828] 0.000000~~-58.500000
2017-08-07 17:01:03.838312+0800 JJOC[8132:3279828] 0.000000~~-59.500000

RAC实现代理方法

#import "JJRACDelegateVC.h"
#import "ReactiveCocoa/ReactiveCocoa.h"

@interface JJRACDelegateVC () <UIScrollViewDelegate>

@property (nonatomic, strong) UITableView *tableView;

@end

@implementation JJRACDelegateVC

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.title = @"代理RAC";
    
    self.view.backgroundColor = [UIColor lightTextColor];
    
    [self setupUI];
    
    [[self rac_signalForSelector:@selector(scrollViewDidScroll:) fromProtocol:@protocol(UIScrollViewDelegate)] subscribeNext:^(RACTuple *tuple) {
        NSLog(@"%@",tuple);
        NSLog(@"%f~~%f",self.tableView.contentOffset.x,self.tableView.contentOffset.y);
    }];
    
    //这里是个坑,必须将代理最后设置,否则信号是无法订阅到的
    self.tableView.delegate = self;
}

#pragma mark - Object Private Function'

- (void)setupUI
{
    UITableView *tableView  = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
    tableView.contentSize = CGSizeMake(2000, 2000);
    [self.view addSubview:tableView];
    self.tableView = tableView;
}

@end

下面看输出结果

2017-08-07 17:34:15.382048+0800 JJOC[8150:3284114] 0.000000~~-62.000000
2017-08-07 17:34:15.398510+0800 JJOC[8150:3284114] <RACTuple: 0x17401b380> (
    "<UITableView: 0x10087da00; frame = (0 0; 375 667); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x170249810>; layer = <CALayer: 0x17003d880>; contentOffset: {0, -62.5}; contentSize: {375, 0}>"
)
2017-08-07 17:34:15.398587+0800 JJOC[8150:3284114] 0.000000~~-62.500000
2017-08-07 17:34:15.431838+0800 JJOC[8150:3284114] <RACTuple: 0x17001b3c0> (
    "<UITableView: 0x10087da00; frame = (0 0; 375 667); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x170249810>; layer = <CALayer: 0x17003d880>; contentOffset: {0, -63}; contentSize: {375, 0}>"
)
2017-08-07 17:34:15.431922+0800 JJOC[8150:3284114] 0.000000~~-63.000000
2017-08-07 17:34:15.481967+0800 JJOC[8150:3284114] <RACTuple: 0x17401b410> (
    "<UITableView: 0x10087da00; frame = (0 0; 375 667); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x170249810>; layer = <CALayer: 0x17003d880>; contentOffset: {0, -63.5}; contentSize: {375, 0}>"

后记

未完,待续~~~

立秋
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容