iOS事件傳遞與響應(yīng)者鏈

用戶以多種方式操縱他們的iOS設(shè)備,例如觸摸屏幕或搖動(dòng)設(shè)備蜻牢。 iOS會(huì)解釋用戶何時(shí)以及如何操作硬件并將此信息傳遞到您的應(yīng)用程序。 您的應(yīng)用程序以自然和直觀的方式響應(yīng)操作的次數(shù)越多似芝,對(duì)用戶而言越有吸引力的體驗(yàn)嵌赠。

一、事件分類

事件是發(fā)送到應(yīng)用程序用于通知用戶操作的對(duì)象忽妒。 在iOS中玩裙,事件可以采取多種形式:多點(diǎn)觸摸事件,運(yùn)動(dòng)事件和用于控制多媒體的事件段直。 這最后一種類型的事件被稱為遙控事件或者遠(yuǎn)程控制事件吃溅,因?yàn)樗梢栽醋酝獠扛郊6谖覀冮_發(fā)過程中最常用的就是多點(diǎn)觸摸事件坷牛。

Event in iOS

二罕偎、事件傳遞與響應(yīng)鏈

當(dāng)您設(shè)計(jì)應(yīng)用程式時(shí)很澄,可能需要?jiǎng)討B(tài)響應(yīng)事件京闰。 例如,觸摸可以發(fā)生在屏幕上的許多不同對(duì)象中甩苛,并且您必須決定您想要那個(gè)對(duì)象響應(yīng)事件蹂楣,并且理解該對(duì)象如何接收該事件。

當(dāng)用戶生成的事件發(fā)生時(shí)讯蒲,UIKit創(chuàng)建一個(gè)包含處理事件所需信息的事件對(duì)象痊土。 然后它將事件對(duì)象放置在活動(dòng)應(yīng)用程序的事件隊(duì)列中。 對(duì)于觸摸事件墨林,該對(duì)象是在UIEvent對(duì)象中打包的一組觸摸赁酝。 對(duì)于運(yùn)動(dòng)事件犯祠,事件對(duì)象因您使用的框架和您感興趣的運(yùn)動(dòng)事件類型而異。

事件沿著特定路徑傳遞酌呆,直到它被傳遞到可以處理它的對(duì)象衡载。 首先,單例UIApplication對(duì)象從隊(duì)列的頂部獲取一個(gè)事件并分發(fā)處理隙袁。 通常痰娱,它將事件發(fā)送到應(yīng)用程序的key window對(duì)象,該對(duì)象將事件傳遞到初始對(duì)象(initial object)進(jìn)行處理菩收。 初始對(duì)象取決于事件的類型梨睁。

  • 觸摸事件:對(duì)于觸摸事件,窗口對(duì)象首先嘗試將事件傳遞到發(fā)生觸摸的視圖娜饵。 該視圖稱為命中測(cè)試視圖(hit-test view)坡贺。 找到命中測(cè)試視圖(hit-test view)的過程稱為命中測(cè)試(hit-testing),這在Hit-Testing返回觸摸發(fā)生的視圖中描述箱舞。

  • 運(yùn)動(dòng)和遙控事件:對(duì)于這些事件拴念,窗口對(duì)象將搖動(dòng)或遠(yuǎn)程控制事件發(fā)送到第一響應(yīng)者以進(jìn)行處理。 第一響應(yīng)者在響應(yīng)者鏈由響應(yīng)者對(duì)象組成中描述褐缠。

這些事件路徑的最終目標(biāo)是找到一個(gè)可以處理和響應(yīng)事件的對(duì)象政鼠。 因此,UIKit首先將事件發(fā)送到最適合處理事件的對(duì)象队魏。 對(duì)于觸摸事件公般,該對(duì)象是命中測(cè)試視圖(hit-test view),對(duì)于其他事件胡桨,該對(duì)象是第一個(gè)響應(yīng)者官帘。 以下部分更詳細(xì)地說明命中測(cè)試視圖(hit-test view)和第一響應(yīng)者對(duì)象是如何確定的。

1. Hit-Testing返回觸摸發(fā)生的視圖

iOS使用命中測(cè)試(hit-testing)來查找被觸摸的視圖昧谊。 命中測(cè)試(hit-testing)涉及檢查觸摸是否在所有相關(guān)視圖對(duì)象的邊界內(nèi)刽虹。 如果是,它會(huì)遞歸檢查視圖的所有子視圖呢诬。視圖層級(jí)中包含觸摸點(diǎn)的最低的視圖成為命中測(cè)試視圖(hit-test view) 涌哲。 iOS確定命中測(cè)試視圖(hit-test view)后,它會(huì)將觸摸事件傳遞到該視圖進(jìn)行處理尚镰。

舉例說明阀圾,假設(shè)用戶觸摸下圖中的View E。 iOS通過按照此順序檢查子視圖來查找命中測(cè)試視圖(hit-test view):

  1. 觸摸在View A的邊界內(nèi)狗唉,因此它檢查子視圖View B和View C.

  2. 觸摸不在View B的界限內(nèi)初烘,但它在View C的界限內(nèi),因此它檢查子視圖View D和View E.

  3. 觸摸不在View D的界限內(nèi),但它在View E的界限內(nèi)肾筐。

    View E是視圖層級(jí)中包含觸摸的最低的視圖哆料,因此它成為命中測(cè)試視圖(hit-test view)。

    Hit-testing returns the subview that was touched

hitTest:withEvent:方法為給定的CGPoint和UIEvent返回一個(gè)點(diǎn)擊測(cè)試視圖(hit-test view)吗铐。hitTest:withEvent:方法首先調(diào)用pointInside:withEvent:方法剧劝。 如果傳遞到hitTest:withEvent:方法的點(diǎn)是在視圖的邊界內(nèi),pointInside:withEvent:返回YES抓歼。然后讥此,在每個(gè)返回YES的子視圖上遞歸調(diào)用hitTest:withEvent:方法 。

如果傳遞到hitTest:withEvent:方法的點(diǎn)不在視圖的邊界內(nèi)谣妻,第一次調(diào)用pointInside:withEvent:方法返回 NO 萄喳,該點(diǎn)被忽略,hitTest:withEvent:返回nil 蹋半。 如果子視圖返回NO他巨,則視圖層級(jí)結(jié)構(gòu)的這個(gè)整個(gè)分支將被忽略,因?yàn)槿绻|摸沒有發(fā)生在該子視圖中减江,則它也不會(huì)出現(xiàn)在該子視圖的任何子視圖中染突。這意味著在子視圖內(nèi)而在父視圖之外的任何點(diǎn)都不能接受點(diǎn)擊事件,因?yàn)橛|摸點(diǎn)必須在父視圖和子視圖邊界內(nèi)辈灼。如果子視圖的clipsToBounds屬性設(shè)置為NO份企,則可能出現(xiàn)此問題。見示例將事件傳遞給子視圖

注:觸摸對(duì)象為其生命周期而關(guān)聯(lián)到其命中測(cè)試視圖(hit-test view)巡莹,即使觸摸稍后移動(dòng)到視圖之外司志。

命中測(cè)試視圖(hit-test view)被給予首先處理觸摸事件的機(jī)會(huì)。 如果命中測(cè)試視圖(hit-test view)無法處理的事件降宅,事件沿著響應(yīng)者鏈向上傳播(如響應(yīng)者鏈由響應(yīng)者對(duì)象組成中描述)骂远,直到系統(tǒng)找到一個(gè)可以處理它的對(duì)象。

2. 響應(yīng)者鏈由響應(yīng)者對(duì)象組成

許多類型的事件依賴于為事件傳遞的響應(yīng)者鏈腰根。 響應(yīng)鏈?zhǔn)且幌盗斜绘溄悠饋淼捻憫?yīng)對(duì)象激才。 它從第一響應(yīng)者開始,到程序?qū)ο螅║IApplication object)結(jié)束额嘿。 如果第一響應(yīng)者不能處理事件瘸恼,它轉(zhuǎn)發(fā)事件到響應(yīng)者鏈中的下一個(gè)響應(yīng)者。

響應(yīng)者對(duì)象是一個(gè)可以響應(yīng)和處理事件的對(duì)象岩睁。 UIResponder類是所有響應(yīng)者對(duì)象的基類钞脂,它不僅為事件處理定義編程接口揣云,也為常見響應(yīng)者行為定義編程接口捕儒。UIApplication, UIViewController和UIView類的實(shí)例都是響應(yīng)者(responder),這意味著所有的視圖和大多數(shù)控制器對(duì)象都是響應(yīng)者刘莹。 注意核心動(dòng)畫層不是響應(yīng)者阎毅。

第一個(gè)響應(yīng)者被指定為第一個(gè)接收事件。 通常点弯,第一響應(yīng)者是視圖對(duì)象扇调。 一個(gè)對(duì)象通過做兩件事情成為第一個(gè)響應(yīng)者:

  1. 重寫canBecomeFirstResponder方法返回YES。
  2. 接收becomeFirstResponder消息抢肛。 如果需要狼钮,對(duì)象可以向自身發(fā)送此消息。

注:請(qǐng)確保您的應(yīng)用程序在指派一個(gè)對(duì)象成為第一個(gè)響應(yīng)者之前已經(jīng)建立了對(duì)象圖(has established its object graph捡絮,個(gè)人感覺應(yīng)該理解為對(duì)象已經(jīng)被渲染完成)熬芜。 例如,您通常在重寫的viewDidAppear:方法中調(diào)用becomeFirstResponder方法福稳。 如果您嘗試在viewWillAppear:中指派第一響應(yīng)者涎拉,你的對(duì)象圖尚未建立(object graph is not yet established,個(gè)人理解為對(duì)象渲染尚未完成)的圆,所以becomeFirstResponder方法返回 NO 鼓拧。

事件不是唯一依賴響應(yīng)者鏈的對(duì)象,響應(yīng)者鏈用于以下所有情況:

  • 觸摸事件(Touch events):如果命中測(cè)試視圖(hit-test view)不能夠處理觸摸事件越妈,事件以命中測(cè)試視圖(hit-test view)為起點(diǎn)沿著響應(yīng)者鏈向上傳遞季俩。
  • 運(yùn)動(dòng)事件(Motion events):為了使用UIKit處理搖動(dòng)動(dòng)作事件,第一響應(yīng)者必須實(shí)現(xiàn)UIResponder類的motionBegan:withEvent:motionEnded:withEvent:的方法梅掠。
  • 遙控事件(Remote control event):為了處理遙控事件种玛,第一響應(yīng)者必須實(shí)現(xiàn)UIResponder類的remoteControlReceivedWithEvent:方法。
  • 動(dòng)作消息(Action messages):當(dāng)用戶操作一個(gè)控制對(duì)象瓤檐,例如一個(gè)按鈕(button)或者開關(guān)(switch)赂韵,并且動(dòng)作方法(action method)的目標(biāo)(target)是nil,則消息以控制視圖為起點(diǎn)沿著響應(yīng)者鏈傳遞挠蛉。參閱示例:將事件傳遞給父視圖
  • 編輯菜單消息(Editing-menu messages):當(dāng)用戶點(diǎn)擊編輯菜單中的命令祭示,iOS使用響應(yīng)者鏈找到實(shí)現(xiàn)了必要方法的對(duì)象(如cut:copy:paste: )谴古。 想了解更多信息质涛,請(qǐng)參閱顯示和管理編輯菜單
  • 文本編輯(Text editing):當(dāng)用戶點(diǎn)擊text field或text view掰担,該視圖自動(dòng)成為第一個(gè)響應(yīng)者汇陆。 默認(rèn)情況下,虛擬鍵盤出現(xiàn)带饱,text field或text view成為編輯的焦點(diǎn)毡代。您可以顯示自定義輸入視圖阅羹,而不是鍵盤。 您還可以向任何響應(yīng)者對(duì)象添加自定義輸入視圖教寂。 想了解更多信息捏鱼,請(qǐng)參閱自定義數(shù)據(jù)輸入視圖

UIKit自動(dòng)設(shè)置用戶點(diǎn)擊的text field或text view為第一個(gè)響應(yīng)者; 應(yīng)用程序必須使用becomeFirstResponder方法顯式設(shè)置所有其他對(duì)象為第一響應(yīng)者酪耕。

3. 響應(yīng)者鏈遵循特定傳遞路徑

如果初始對(duì)象(命中測(cè)試視圖或第一個(gè)響應(yīng)者)不處理事件导梆,UIKit將事件傳遞給鏈中的下一個(gè)響應(yīng)者。 每個(gè)響應(yīng)者決定是否它要處理事件或通過調(diào)用其nextRsponder方法傳遞給它自己的下一個(gè)響應(yīng)者迂烁。這種處理持續(xù)進(jìn)行看尼,直到一個(gè)響應(yīng)者對(duì)象處理事件或有沒有更多的響應(yīng)者。

當(dāng)iOS檢測(cè)到事件并將其傳遞給初始對(duì)象(通常是視圖)時(shí)盟步,響應(yīng)者鏈序列開始狡忙。 初始視圖擁有第一機(jī)會(huì)處理事件。下圖顯示了兩個(gè)不同配置應(yīng)用程序的兩個(gè)不同事件傳遞路徑址芯。應(yīng)用程序的事件傳遞路徑取決于其特定結(jié)構(gòu)灾茁,但所有事件傳遞路徑都遵循相同的探視程序。

The responder chain on iOS

對(duì)于左側(cè)的應(yīng)用程序谷炸,事件遵循以下路徑:

  1. 初始視圖試圖處理該事件或消息北专。如果它不能處理這個(gè)事件,它將事件傳遞到其父視圖 旬陡,因?yàn)槌跏家晥D在它的視圖控制器的視圖層次中不是最頂部的視圖拓颓。
  2. 父視圖嘗試處理該事件。如果父視圖不能處理事件描孟,它將事件傳遞到其超級(jí)視圖驶睦,因?yàn)樗匀徊皇且晥D層次中最頂部的視圖。
  3. 視圖控制器的視圖層次中最頂層視圖嘗試處理該事件匿醒。如果最頂層的視圖不能處理事件场航,它將事件傳遞到它的視圖控制器。
  4. 視圖控制器嘗試處理該事件廉羔,如果不能溉痢,將事件傳遞到窗口。
  5. 如果窗口對(duì)象不能處理該事件憋他,傳遞事件到單例應(yīng)用程序?qū)ο蟆?/li>
  6. 如果應(yīng)用程序?qū)ο?/strong>不能處理這個(gè)事件孩饼,它丟棄該事件。

右側(cè)的應(yīng)用程序遵循稍微不同的路徑竹挡,但所有事件傳遞路徑遵循以下探視程序:

  1. 視圖在其視圖控制器的視圖層次結(jié)構(gòu)上向上傳遞事件镀娶,直到它到達(dá)最頂層視圖。

  2. 最頂層視圖將事件傳遞到其視圖控制器揪罕。

  3. 視圖控制器將事件傳遞到其最頂層視圖的父視圖梯码。

    重復(fù)步驟1-3宝泵,直到事件到達(dá)根視圖控制器。

  4. 根視圖控制器將事件傳遞到窗口對(duì)象忍些。

  5. 窗口將事件傳遞給應(yīng)用程序?qū)ο蟆?/p>

重要提示:如果您實(shí)現(xiàn)一個(gè)自定義視圖來處理遙控事件鲁猩,動(dòng)作消息坎怪,UIKit的搖移動(dòng)事件罢坝,或編輯菜單消息,不要直接轉(zhuǎn)發(fā)事件或消息到nextResponder來沿響應(yīng)者鏈向上傳遞搅窿。 相反嘁酿,調(diào)用當(dāng)前事件處理方法的超類實(shí)現(xiàn),讓UIKit處理響應(yīng)者鏈的遍歷男应。

三闹司、應(yīng)用

從事件傳遞與響應(yīng)者鏈的內(nèi)容思考一些應(yīng)用例子。

1. 擴(kuò)大視圖的點(diǎn)擊區(qū)域

一個(gè)按鈕的尺寸是20*20沐飘,如果要擴(kuò)大按鈕的點(diǎn)擊區(qū)域(上下左右各擴(kuò)大10)游桩,有以下處理方法:

  • 按鈕設(shè)置image,然后按鈕的size設(shè)置的比實(shí)際大一倍耐朴。
  • 在按鈕上覆蓋一層較大的View或者Button借卧,設(shè)置點(diǎn)擊事件。
  • 自定義Button筛峭,覆蓋hitTest:withEvent:或者pointInside:withEvent:方法铐刘。

我們只舉例說明第三種方法:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    if (self.userInteractionEnabled == NO || self.hidden || self.alpha <= 0.01) {
        return nil;
    }
    
    CGRect responseRect = CGRectInset(self.bounds, -10, -10);
    if (CGRectContainsPoint(responseRect, point)) {
        for (UIView *subView in [self.subviews reverseObjectEnumerator]) {
            CGPoint convertedPoint = [subView convertPoint:point fromView:self];
            UIView *hitTestView = [subView hitTest:convertedPoint withEvent:event];
            if (hitTestView) {
                return hitTestView;
            }
        }
        return self;
    }
    return nil;
}

或者

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    NSLog(@"%s", __PRETTY_FUNCTION__);   
    CGRect bounds = CGRectInset(self.bounds, -10, -10);
    return CGRectContainsPoint(bounds, point);
}

2. 將事件傳遞給父視圖

在controller中有一個(gè)YKNoteEventHandingView,其上面再添加一個(gè)YKNoteEventHandlingButton影晓,點(diǎn)擊Button將事件傳遞到View镰吵。有以下幾種做法:

  • Button的- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event方法返回nil,hit-test view為父視圖

  • YKNoteEventHandingView的- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event方法返回self挂签,阻止事件傳遞給子視圖

  • 設(shè)置Button的target為nil疤祭,Button無法處理事件響應(yīng),事件沿著響應(yīng)者鏈向上傳遞饵婆,傳遞到父視圖画株。示例如下

#import "YKNoteEventHandingView.h"

@implementation YKNoteEventHandingView
//在View中寫一個(gè)action方法,判斷View中的Button的target為nil的時(shí)候是否會(huì)執(zhí)行啦辐,若執(zhí)行谓传,則消息沿著響應(yīng)者鏈向上傳遞了
- (void)ykNoteEventHandlingGreenButtonDidTouchUpInside:(UIButton *)button {
    NSLog(@"%s \n %@", __PRETTY_FUNCTION__, button);
}

@end
  
#import "YKNoteEventHandlingButton.h"
//在Button中寫一個(gè)action方法,判斷Button的target為nil的時(shí)候是否會(huì)執(zhí)行芹关,若執(zhí)行续挟,則消息沿著響應(yīng)者鏈傳遞了
@implementation YKNoteEventHandlingButton

- (void)ykNoteEventHandlingGreenButtonDidTouchUpInside:(UIButton *)button {
    NSLog(@"%s \n %@", __PRETTY_FUNCTION__, button);
}
#import "YKNoteEventHandingViewController.h"
#import "YKNoteEventHandingView.h"
#import "YKNoteEventHandlingButton.h"

@interface YKNoteEventHandingViewController ()

@property (nonatomic, strong) YKNoteEventHandingView *yKNoteEventHandingView;
@property (nonatomic, strong) YKNoteEventHandlingButton *ykNoteEventHandlingButton;

@end

@implementation YKNoteEventHandingViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.title = @"EventHandling";
    self.view.backgroundColor = [UIColor whiteColor];
    //View
    [self.yKNoteEventHandingView setFrame:CGRectMake(50, 100, 200, 200)];
    [self.view addSubview:self.yKNoteEventHandingView];

    //Button
    [self.ykNoteEventHandlingButton setFrame:CGRectMake(60, 60, 100, 100)];
    [self.yKNoteEventHandingView addSubview:self.ykNoteEventHandlingButton];
}

#pragma mark - event
- (void)ykNoteEventHandlingGreenButtonDidTouchUpInside:(UIButton *)button {
    NSLog(@"%s \n %@", __PRETTY_FUNCTION__, button);
}

#pragma mark - getter
- (YKNoteEventHandingView *)yKNoteEventHandingView {
    if (_yKNoteEventHandingView == nil) {
        _yKNoteEventHandingView = [[YKNoteEventHandingView alloc] init];
        _yKNoteEventHandingView.backgroundColor = [UIColor redColor];
    }
    return _yKNoteEventHandingView;
}

- (YKNoteEventHandlingButton *)ykNoteEventHandlingButton {
    if (_ykNoteEventHandlingButton == nil) {
        _ykNoteEventHandlingButton = [[YKNoteEventHandlingButton alloc] init];
        _ykNoteEventHandlingButton.backgroundColor = [UIColor greenColor];
        [_ykNoteEventHandlingButton addTarget:nil action:@selector(ykNoteEventHandlingGreenButtonDidTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
    }
    return _ykNoteEventHandlingButton;
}
  //Button的target設(shè)置為nil的時(shí)候,執(zhí)行了YKNoteEventHandlingButton中的方法侥衬,說明target為nil的時(shí)候事件沿著響應(yīng)者鏈傳遞了
  -[YKNoteEventHandlingButton ykNoteEventHandlingGreenButtonDidTouchUpInside:] 
   <YKNoteEventHandlingButton: 0x100224950; baseClass = UIButton; frame = (60 60; 100 100); opaque = NO; layer = <CALayer: 0x17002a1a0>>

  //注釋掉Button中的方法诗祸。輸出內(nèi)容如下跑芳,說明事件沿著響應(yīng)者鏈向上傳遞了。
  -[YKNoteEventHandingView ykNoteEventHandlingGreenButtonDidTouchUpInside:] 
   <YKNoteEventHandlingButton: 0x10030fe40; baseClass = UIButton; frame = (60 60; 100 100); opaque = NO; layer = <CALayer: 0x17003d520>>

  //注釋掉Button和View中的方法直颅。輸出內(nèi)容如下博个,說明事件沿著響應(yīng)者鏈向上傳遞了。
  -[YKNoteEventHandingViewController ykNoteEventHandlingGreenButtonDidTouchUpInside:] 
   <YKNoteEventHandlingButton: 0x100402fd0; baseClass = UIButton; frame = (60 60; 100 100); opaque = NO; layer = <CALayer: 0x1740315a0>>

3. 將事件傳遞給兄弟視圖

假設(shè)有下圖所示的布局功偿,我們希望點(diǎn)擊view C的時(shí)候view B響應(yīng)事件盆佣,而點(diǎn)擊View D和View E的時(shí)候正常響應(yīng)。這個(gè)時(shí)候通過重寫view C的hittest可以解決這個(gè)問題械荷,在C的hittest里面直接返回nil就行了共耍。

Hit-testing returns the subview that was touched
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    
    UIView *hitTestView = [super hitTest:point withEvent:event];
    if (hitTestView == self) {
        return nil;
    }
    return hitTestView;    
}

4. 將事件傳遞給子視圖

如下圖,banner為CollectionView中的一個(gè)樓層吨瞎,CollectionViewCell中有個(gè)scrollView痹兜,scrollView中為圖片,現(xiàn)在將cell的寬度縮小一半(變?yōu)樗{(lán)色框部分)颤诀,設(shè)置cell和scrollview的clipsToBounds為NO字旭,現(xiàn)在在右側(cè)處滑動(dòng),scrollview中的圖片顯然不會(huì)滑動(dòng)崖叫,因?yàn)椴粷M足pointInside:withEvent:遗淳,這時(shí)只需要修改cell的- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event方法,返回scrollview即可归露。

傳遞事件到子視圖
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView *hitTestView = [super hitTest:point withEvent:event];
    if (hitTestView == nil) {
        hitTestView = self.scrollView;
    }
    return hitTestView;
}

參考:

https://developer.apple.com/library/content/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/Introduction/Introduction.html

https://developer.apple.com/library/content/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/event_delivery_responder_chain/event_delivery_responder_chain.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末洲脂,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子剧包,更是在濱河造成了極大的恐慌恐锦,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疆液,死亡現(xiàn)場(chǎng)離奇詭異一铅,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)堕油,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門潘飘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人掉缺,你說我怎么就攤上這事卜录。” “怎么了眶明?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵艰毒,是天一觀的道長。 經(jīng)常有香客問我搜囱,道長丑瞧,這世上最難降的妖魔是什么柑土? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮绊汹,結(jié)果婚禮上稽屏,老公的妹妹穿的比我還像新娘。我一直安慰自己西乖,他們只是感情好狐榔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著浴栽,像睡著了一般荒叼。 火紅的嫁衣襯著肌膚如雪轿偎。 梳的紋絲不亂的頭發(fā)上典鸡,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音坏晦,去河邊找鬼萝玷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛昆婿,可吹牛的內(nèi)容都是我干的球碉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼仓蛆,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼睁冬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起看疙,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤豆拨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后能庆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體施禾,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年搁胆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了弥搞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡渠旁,死狀恐怖攀例,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情顾腊,我是刑警寧澤粤铭,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站投慈,受9級(jí)特大地震影響承耿,放射性物質(zhì)發(fā)生泄漏冠骄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一加袋、第九天 我趴在偏房一處隱蔽的房頂上張望凛辣。 院中可真熱鬧,春花似錦职烧、人聲如沸扁誓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蝗敢。三九已至,卻和暖如春足删,著一層夾襖步出監(jiān)牢的瞬間寿谴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來泰國打工失受, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留讶泰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓拂到,卻偏偏與公主長得像痪署,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子兄旬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

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