iOS WebView的封装 - 适用于原生App与h5交互

QZWebView

WebView的简单封装 - 适用于原生App与h5交互

GitHub:https://github.com/quzhongyeluo/QZWebView

现在的新项目基本上都是最低适配iOS 8了,毕竟现在中国的社交巨无霸QQ和微信都是最低适配iOS 8,除非...老板特别要求的要适配iOS 7...无奈.,兼容iOS 7真的要花很多时间。最近在重构项目,现在简单说一下WebView的封装!适用于原生App与h5交互

iOS 7使用UIWebView

iOS 8及以上系统使用WKWebView(好处不说了,坑也不说了,网上一大把)

使用方法:
导入QZWebView.m QZWebView.h

如果需要控制器还需导入QZWebViewViewController.m QZWebViewViewController.h

QZWebView *webView = [[QZWebView alloc] initWithFrame:self.view.bounds url:yoururl];
[self.view addSubview:webView];

或者

QZWebView *webView = [[QZWebView alloc] initWithFrame:self.view.bounds filePath:self.filePath];
[self.view addSubview:webView];

使用控制器例子:

QZWebViewViewController *vc = [[QZWebViewViewController alloc] initWithURL:@"https://www.baidu.com"];
[self.navigationController pushViewController:vc animated:true];

本地初始化就不写例子了,涉及到公司的项目的信息

如果iOS 9及以上系统访问失败,请检查是否开启了http访问的权限。

自定义需要修改的地方:
1、本地html文件所在的文件位置
baseURL:本地html文件所在的文件夹

2、自定义的需要拦截的链接,进行与h5交互

WKWebView改:

/*
 在发送请求之前,决定是否跳转
 decisionHandler必须调用,来决定是否跳转,
 WKNavigationActionPolicyCancel取消跳转
 WKNavigationActionPolicyAllow 允许跳转
 */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{

    // 如果 targetFrame 的 mainFrame 属性为NO,表明这个 WKNavigationAction 将会新开一个页面。
    if (!navigationAction.targetFrame.isMainFrame) {
        [webView evaluateJavaScript:@"var a = document.getElementsByTagName('a');for(var i=0;i<a.length;i++){a[i].setAttribute('target','');}" completionHandler:nil];
    }

    // 对截获的URL进行自定义操作

    // 获取URL
    NSString *urlString = [[navigationAction.request URL] absoluteString];
    // 把URL转成UTF8编码
    NSString *UTF8URL = [NSString stringWithString:[urlString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    if ([UTF8URL rangeOfString:@"自定义"].length != 0) {

        // 被拦截,不允许跳转(进行自定义操作)

        decisionHandler(WKNavigationActionPolicyCancel);
    }else{
        // 允许跳转
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}

UIWebView改:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    // 获取URL
    NSString *urlString = [[request URL] absoluteString];
    // 把URL转成UTF8编码
    NSString *UTF8URL = [NSString stringWithString:[urlString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    if ([UTF8URL rangeOfString:@"自定义"].length != 0) {

        // 被拦截,不允许跳转(进行自定义操作)

        return NO;
    }else{
        // 允许跳转
        return YES;
    }

}

Github:https://github.com/quzhongyeluo/QZWebView


直接看代码吧!代码有详细的注释

QZWebView.h

//
//  QZWebView.h
//  QZWebView
//
//  Created by 曲终叶落 on 2017/7/13.
//  Copyright © 2017年 曲终叶落. All rights reserved.
//

#import <UIKit/UIKit.h>

@protocol QZWebViewDelegate <NSObject>

@optional

/**
 页面开始加载时调用
 */
- (void)didStartProvisional;

/**
 开始获取到网页内容时返回
 */
- (void)didCommit;

/**
 加载完成
 */
- (void)didFinish;

/**
 加载失败
 */
- (void)didFailProvisional;


- (void)scrollViewDidScroll:(UIScrollView *)scrollView;

- (void)scrollViewWillEndDragging;

- (void)webViewTitle:(NSString *)title;

@end

/**
 WebView封装:
 iOS7 : UIWebView
 iOS8 : WKWebView
 */
@interface QZWebView : UIView

@property (nonatomic,weak) id<QZWebViewDelegate>deleget;

/**
 通过网页链接初始化

 @param frame frame
 @param url 网页链接
 @return webView
 */
- (instancetype)initWithFrame:(CGRect)frame url:(NSString *)url;


/**
 通过本地链接初始化

 @param frame frame
 @param filePath 本地链接
 @return webView
 */
- (instancetype)initWithFrame:(CGRect)frame filePath:(NSString *)filePath;

/**
 加载JSON数据(需要在webView加载完成后使用)

 @param json json数据
 */
- (void)loadingWithJSON:(NSString *)json;


@end

QZWebView.m

//
//  QZWebView.m
//  QZWebView
//
//  Created by 曲终叶落 on 2017/7/13.
//  Copyright © 2017年 曲终叶落. All rights reserved.
//

#import "QZWebView.h"
#import <WebKit/WebKit.h>


/*-------------------- 系统版本 --------------------*/
/**
 iOS 7
 */
#define TARGET_iOS7 [[UIDevice currentDevice].systemVersion doubleValue] < 8.0 && [[UIDevice currentDevice].systemVersion doubleValue] >= 7.0

/**
 iOS 8
 */
#define TARGET_iOS8 [[UIDevice currentDevice].systemVersion doubleValue] < 9.0 && [[UIDevice currentDevice].systemVersion doubleValue] >= 8.0

/**
 iOS 8及iOS 8以后的系统
 */
#define TARGET_iOS8Later [[UIDevice currentDevice].systemVersion doubleValue] >= 8.0

/**
 iOS 9及iOS9以后的系统
 */
#define TARGET_iOS9Later [[UIDevice currentDevice].systemVersion doubleValue] >= 9.0

// 加载模式
typedef enum{
    // 在线
    LoadRequest,
    // 本地HTML
    LoadHTML

}QZWebViewLoadType;

@interface QZWebView () <UIWebViewDelegate,UIActionSheetDelegate,WKNavigationDelegate,UIScrollViewDelegate,WKScriptMessageHandler,WKUIDelegate>

@property (nonatomic,strong) UIWebView *uiWebView;
@property (nonatomic,strong) WKWebView *wkWebView;
/**
 加载模式
 */
@property (nonatomic, assign) QZWebViewLoadType loadType;

/**
 URL:可能是本地链接、在线链接
 */
@property (nonatomic, copy ) NSURL *url;

@end

@implementation QZWebView

#pragma mark - 初始化

- (instancetype)initWithFrame:(CGRect)frame url:(NSString *)url{
    if (self = [super initWithFrame:frame]) {
        _url = [NSURL URLWithString:url];
        _loadType = LoadRequest;
        [self loadData];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame filePath:(NSString *)filePath{
    if (self = [super initWithFrame:frame]) {
        _url = [NSURL fileURLWithPath:filePath];
        _loadType = LoadHTML;
        [self loadData];
    }
    return self;
}

/**
 开始加载在线数据或者加载本地html文件
 */
- (void)loadData{
    switch (_loadType) {
        case LoadRequest:{
            // 在线链接
            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:_url];
            if (TARGET_iOS8Later) {
                [self.wkWebView loadRequest:request];
            }else{
                [self.uiWebView loadRequest:request];
            }
        }
            break;

        default:{
            // 加载本地文件 ()

            // 本地文件所在的文件夹位置
            // NSString *baseURL = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"web"];
            NSString *baseURL = @"";
            // 获取本地html的信息
            NSString *html = [NSString stringWithContentsOfURL:_url encoding:NSUTF8StringEncoding error:nil];

            if (TARGET_iOS7) {

                [self.uiWebView loadHTMLString:html baseURL:[NSURL fileURLWithPath:baseURL]];

            }else if (TARGET_iOS9Later){

                [self.wkWebView loadHTMLString:html baseURL:[NSURL fileURLWithPath:baseURL]];

            }else{
                /*
                 在iOS8系统中,WKWebView使用loadHTMLString会出现不加载CSS和JS的问题
                 应使用loadRequest加载

                 另外WKWebView在iOS 8是不能加载NSBundle、NSHomeDirectory等位置的文件,只能加载NSTemporaryDirectory的文件,所以需要把本地文件复制到NSTemporaryDirectory里面
                 */
                // [self copyWebToTemp];
                // NSString *webpath = [NSTemporaryDirectory() stringByAppendingString:@"web"];
                NSString *webpath = @"";

                NSString *path = [NSString stringWithFormat:@"%@/%@",webpath,_url.lastPathComponent];

                NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]];

                [self.wkWebView loadRequest:request];
            }
        }
            break;
    }
}

#pragma mark - 处理json数据

/**
 加载JSON数据(需要在webView加载完成后使用)

 @param json json数据
 */
- (void)loadingWithJSON:(NSString *)json{
    if (TARGET_iOS8Later) {
        [self.wkWebView evaluateJavaScript:json completionHandler:^(id item, NSError * _Nullable error) {
            // Block中处理是否通过了或者执行JS错误的代码
            NSLog(@"%@",item);
            NSLog(@"%@",error);
        }];
    }else{
        [self.uiWebView stringByEvaluatingJavaScriptFromString:json];
    }
}

#pragma mark - WKWebView代理

// 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigatio{
    if ([self.deleget respondsToSelector:@selector(didStartProvisional)]) {
        [self.deleget didStartProvisional];
    }
}

// 开始获取到网页内容时返回
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
    if ([self.deleget respondsToSelector:@selector(didCommit)]) {
        [self.deleget didCommit];
    }
}

// 页面加载完成
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{

    if ([self.deleget respondsToSelector:@selector(didFinish)]) {
        [self.deleget didFinish];
    }
    
}

// 页面加载失败
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error{
    if ([self.deleget respondsToSelector:@selector(didFailProvisional)]) {
        [self.deleget didFailProvisional];
    }

}

// 接收到服务器跳转请求之后调用 (服务器端redirect),不一定调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{

}

/*
 在收到服务器的响应头,根据response相关信息,决定是否跳转。
 decisionHandler必须调用,来决定是否跳转,
 WKNavigationResponsePolicyCancel取消跳转
 WKNavigationResponsePolicyAllow 允许跳转
 */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
    decisionHandler(WKNavigationResponsePolicyAllow);
}

/*
 在发送请求之前,决定是否跳转
 decisionHandler必须调用,来决定是否跳转,
 WKNavigationActionPolicyCancel取消跳转
 WKNavigationActionPolicyAllow 允许跳转
 */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{

    // 如果 targetFrame 的 mainFrame 属性为NO,表明这个 WKNavigationAction 将会新开一个页面。
    if (!navigationAction.targetFrame.isMainFrame) {
        [webView evaluateJavaScript:@"var a = document.getElementsByTagName('a');for(var i=0;i<a.length;i++){a[i].setAttribute('target','');}" completionHandler:nil];
    }

    // 对截获的URL进行自定义操作

    // 获取URL
    NSString *urlString = [[navigationAction.request URL] absoluteString];
    // 把URL转成UTF8编码
    NSString *UTF8URL = [NSString stringWithString:[urlString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    if ([UTF8URL rangeOfString:@"自定义"].length != 0) {

        // 被拦截,不允许跳转(进行自定义操作)

        decisionHandler(WKNavigationActionPolicyCancel);
    }else{
        // 允许跳转
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}

// web界面中有弹出警告框时调用
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{

    NSLog(@"%@",message);
}

-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(NO);
    }])];
    [alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler(YES);
    }])];

    [[[[UIApplication sharedApplication] keyWindow] rootViewController] presentViewController:alertController animated:YES completion:nil];
}

// 从web界面中接收到一个脚本时调用
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{

}


#pragma mark - UIWebView代理
// 开始加载
- (void)webViewDidStartLoad:(UIWebView *)webView{
    if ([self.deleget respondsToSelector:@selector(didStartProvisional)]) {
        [self.deleget didStartProvisional];
    }
}

// 加载完成
- (void)webViewDidFinishLoad:(UIWebView *)webView{
    if ([self.deleget respondsToSelector:@selector(didFinish)]) {
        [self.deleget didFinish];
    }
    // 获取title
    if ([self.deleget respondsToSelector:@selector(webViewTitle:)]) {
        NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
        [self.deleget webViewTitle:title];
    }
}

// 加载失败
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
    if ([self.deleget respondsToSelector:@selector(didFailProvisional)]) {
        [self.deleget didFailProvisional];
    }
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    // 获取URL
    NSString *urlString = [[request URL] absoluteString];
    // 把URL转成UTF8编码
    NSString *UTF8URL = [NSString stringWithString:[urlString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    if ([UTF8URL rangeOfString:@"自定义"].length != 0) {

        // 被拦截,不允许跳转(进行自定义操作)

        return NO;
    }else{
        // 允许跳转
        return YES;
    }

}

#pragma mark - scrollView代理
/**
 *  解决iOS9系统bug
 *
 *  在iOS9系统中使用WKWebView时,滚动的时候缺少惯性,滚动幅度小,使用此方法可解决
 */
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    if ([[UIDevice currentDevice].systemVersion doubleValue] >= 9.0 && [[UIDevice currentDevice].systemVersion doubleValue] < 10.0) {
        scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
    }
}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    if ([self.deleget respondsToSelector:@selector(scrollViewDidScroll:)]) {
        [self.deleget scrollViewDidScroll:scrollView];
    }
}

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{

    if ([self.deleget respondsToSelector:@selector(scrollViewWillEndDragging)]) {
        [self.deleget scrollViewWillEndDragging];
    }
}

#pragma mark - dealloc
- (void)dealloc{
    if (TARGET_iOS8Later) {
        // 不把wkWebView.scrollView.delegate 置为空在模拟器上会出现奔溃现象
        self.wkWebView.scrollView.delegate = nil;
        [self.wkWebView removeObserver:self forKeyPath:@"title"];
    }else{
        self.uiWebView.scrollView.delegate = nil;
    }
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    NSLog(@"webView已被释放");
}

#pragma mark - KVO

// 设置iOS 8及以上的标题
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    if ([keyPath isEqualToString:@"title"])
    {
        if (object == self.wkWebView) {
            // 此处可以获取到标题信息
            NSLog(@"%@",self.wkWebView.title);

            if ([self.deleget respondsToSelector:@selector(webViewTitle:)]) {
                [self.deleget webViewTitle:self.wkWebView.title];
            }

        }else{
            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
        }
    }else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

#pragma mark - get and set
- (UIWebView *)uiWebView{
    if (!_uiWebView) {

        UIWebView *web = [[UIWebView alloc] initWithFrame:self.bounds];
        web.delegate = self;

        // YES 加载网页中的电话号码,单击可以拨打
        web.dataDetectorTypes = NO;
        // 适应屏幕
        web.scalesPageToFit = YES;

        web.backgroundColor = [UIColor whiteColor];
        web.multipleTouchEnabled = true;
        web.scrollView.delegate = self;
        web.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;

        [self addSubview:web];

        _uiWebView = web;
    }
    return _uiWebView;
}

- (WKWebView *)wkWebView{
    if (!_wkWebView) {
        WKWebView *wkWebView = [[WKWebView alloc] initWithFrame:self.bounds];
        wkWebView.UIDelegate = self;
        wkWebView.navigationDelegate = self;
        wkWebView.backgroundColor = [UIColor whiteColor];
        /*! 解决iOS9.2以上黑边问题 */
        wkWebView.opaque = false;
        wkWebView.multipleTouchEnabled = true;
        wkWebView.scrollView.delegate = self;
        wkWebView.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;

        [wkWebView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];

        [self addSubview:wkWebView];
        _wkWebView = wkWebView;

    }
    return _wkWebView;
}

@end

WebView封装就完了,根据使用需求选择初始化方法。


为了方便使用顺便封装一个QZWebViewViewController:

QZWebViewViewController.h

//
//  QZWebViewViewController.h
//  QZWebView
//
//  Created by 曲终叶落 on 2017/7/13.
//  Copyright © 2017年 曲终叶落. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface QZWebViewViewController : UIViewController

/**
 通过网页链接初始化

 @param url 链接
 @return return value description
 */
- (instancetype)initWithURL:(NSString *)url;


/**
 通过本地文件初始化

 @param filePath 本地文件位置
 @return return value description
 */
- (instancetype)initWithFilePath:(NSString *)filePath;

@end

QZWebViewViewController.m

//
//  QZWebViewViewController.m
//  QZWebView
//
//  Created by 曲终叶落 on 2017/7/13.
//  Copyright © 2017年 曲终叶落. All rights reserved.
//

#import "QZWebViewViewController.h"
#import "QZWebView.h"

@interface QZWebViewViewController () <QZWebViewDelegate>

@property (nonatomic,  copy ) NSString *url;

@property (nonatomic, strong) QZWebView *webView;

@property (nonatomic,  copy ) NSString *filePath;

@property (nonatomic, strong) UIActivityIndicatorView *activityIndicatorView;

@end

@implementation QZWebViewViewController

#pragma mark - 初始化
- (instancetype)initWithURL:(NSString *)url{
    if (self = [super init]) {
        self.url = url;
    }
    return self;
}

- (instancetype)initWithFilePath:(NSString *)filePath{
    if (self = [super init]) {
        self.filePath = filePath;
    }
    return self;
}

#pragma mark -
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    [self webView];

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - QZWebView代理
- (void)webViewTitle:(NSString *)title{
    self.title = title;
}

/**
 网页开始加载
 */
- (void)didStartProvisional{
    [self.activityIndicatorView startAnimating];
}

/**
 加载完成
 */
- (void)didFinish{
    [self.activityIndicatorView stopAnimating];
}

#pragma mark - get and set
- (QZWebView *)webView{

    if (!_webView) {

        if (self.url) {
            _webView = [[QZWebView alloc] initWithFrame:self.view.bounds url:self.url];
            [self.view addSubview:_webView];
        }else{
            _webView = [[QZWebView alloc] initWithFrame:self.view.bounds filePath:self.filePath];
            [self.view addSubview:_webView];
        }

        _webView.deleget = self;

    }
    return _webView;
}

- (UIActivityIndicatorView *)activityIndicatorView{
    if (!_activityIndicatorView) {
        _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyleWhiteLarge)];
        _activityIndicatorView.frame = CGRectMake(0, 0, 100, 100);
        _activityIndicatorView.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
        _activityIndicatorView.color = [UIColor grayColor];
        [self.view addSubview:_activityIndicatorView];
    }
    return _activityIndicatorView;
}

@end


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

推荐阅读更多精彩内容