IOS 基礎(一)事件旬薯,響應鏈機制分析

@[TOC](IOS 事件般又,響應鏈機制分析)

1. 事件分發(fā)和響應者鏈條

1.1 簡述

  • 事件分發(fā):自上而下的由UIApplication開始,一路往最具體的View查找丐黄,直到找到最應該處理并且能夠處理事件的那個控件斋配。
  • 響應者鏈條:當找到那個最應該處理并且能夠處理事件的那個控件以后,如果這個控件確實處理了這個事件灌闺,那么這個事件的就到此處理完畢艰争,但是很有可能出現(xiàn)的情況是,雖然這個控件最應該處理桂对,也能夠處理事件甩卓,但是它并沒有處理事件,那么這時這個事件就要傳給下一個響應者處理蕉斜,下一個響應者還不處理逾柿,那就再下一個,這個事件就沿著這條響應者鏈條找直到響應者確實處理了這個事件(并中斷了事件傳遞宅此,就是在touch方法里沒有調(diào)用下一個響應者的touch方法)為止

事件的分發(fā)路徑和響應者鏈條的路徑并不是同一條路從兩頭走的關系机错。首先,事件分發(fā)時候除了最開始的UIApplication诽凌,一路都是在查找下一個更應該響應的UIView毡熏,而響應者鏈條除了考慮UIView以外還有其他的UIResponder,例如UIViewController坦敌;其次侣诵,事件分發(fā)會考慮同級UIView之間的關系,就是如果一個UIView有多個子View狱窘,那么哪個是更應該響應的View杜顺,而響應者鏈條則不會考慮同級View之間的關系,一個View的下一個響應者并不會考慮除了自己以為其它適合響應的同級View蘸炸,而是之間考慮它的父View或者是控制器躬络。

2. 事件分發(fā)

當我們手指觸摸屏幕時,系統(tǒng)會生成UITouch對象(一個手指一個UITouch)搭儒,然后系統(tǒng)又會幫我們把所有的UITouch對象包裝成一個UIEvent穷当,然后把這個UIEvent交給UIApplication單例維護著的一個事件隊列提茁,當輪到這個事件處理的時候,UIApplication首先會將這個UIEvent交給KeyWindow馁菜,然后KeyWindow再交給它的根控制器的View茴扁,然后不斷的遞歸尋找最適合處理這個事件的View。
這個遞歸查找的方法叫做hitTest
下面我們嘗試的寫一下這個方法的實現(xiàn):

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    //如果不能處理,返回nil
    if (self.hidden==YES||self.alpha<=0.01||self.userInteractionEnabled == NO) {
        return nil;
    }
    
    //如果不應該處理返回nil
    if ([self pointInside:point withEvent:event]==NO) {
        return nil;
    }
    
    //找找看有沒有更適合處理的子View
    
    //最后添加的(也就是最上面的View)先處理
    NSArray *reverseArray = [[self.subviews reverseObjectEnumerator]allObjects];
    for (UIView *subView  in reverseArray) {
        
        CGPoint subPoint = [self convertPoint:point toView:subView];
        UIView *resultView = [subView hitTest:subPoint withEvent:event];
        
        if (resultView) {
            return resultView;
        }
    }
    
    //遍歷完都沒有子控件更適合,那么最適合的就是自己
    return self;
}

3. 響應者鏈條

當找到這個最適合的控件后汪疮,會從這個控件開始嘗試處理事件并傳遞給下一個響應者(直到某個響應者中斷了傳遞)峭火。
那么,怎么尋找下一個響應者呢智嚷?原則如下:

如果這個view是一個控制器的View那么這個View的下一個響應者就是控制器卖丸。
如果這個View不是控制器的View那么下一個響應者就是它的父View。
根控制器的下一個響應者是誰UIWindow盏道,再下一個響應者是UIApplication稍浆,鏈條結束。

如果我們把A控制器的View添加到B控制器的View上猜嘱,那么A控制器會在響應者鏈條上嗎粹湃,如果在,它的下一個響應者是誰泉坐?
如果要把A控制器添加到響應者鏈條为鳄,就要B控制器add A為子控制器,如果不add的話A控制器不會在這個響應者鏈條內(nèi)腕让,A控制器的下一個響應者為A控制器View的父View孤钦。

  1. 響應鏈是如何工作,正確找到應該響應該事件的響應者的纯丸?

UIKit使用基于視圖的hit-testing來確定touch事件發(fā)生的位置偏形。具體解釋就是,UIKit將touch的位置和視圖層級中的view的邊界進行了比較觉鼻,UIView的方法 hitTest:withEvent: 在視圖層級中進行俊扭,尋找包含指定touch的最深子視圖。這個視圖成為touch事件的第一個響應者坠陈。
說白了就是萨惑,當有touch事件來的時候,會從最下面的視圖開始執(zhí)行 hitTest:withEvent: 仇矾,如果符合成為響應者的條件庸蔼,就會繼續(xù)遍歷它的 subviews 繼續(xù)執(zhí)行 hitTest:withEvent: ,直到找到最合適的view成為響應者贮匕。

  1. 符合響應者的條件包括:
  1. touch事件的位置在響應者區(qū)域內(nèi)
  2. 響應者 hidden 屬性不為 YES
  3. 響應者 透明度 不是 0
  4. 響應者 userInteractionEnabled 不為 NO
  1. 響應者鏈有以下特點:

1姐仅、響應者鏈通常是由視圖(UIView)構成的;
2、一個視圖的下一個響應者是它視圖控制器(UIViewController)(如果有的話)掏膏,然后再轉(zhuǎn)給它的父視圖(Super View)劳翰;
3、視圖控制器(如果有的話)的下一個響應者為其管理的視圖的父視圖馒疹;
4磕道、單例的窗口(UIWindow)的內(nèi)容視圖將指向窗口本身作為它的下一個響應者
需要指出的是,Cocoa Touch應用不像Cocoa應用行冰,它只有一個UIWindow對象溺蕉,因此整個響應者鏈要簡單一點;

4. 事件傳遞和響應原理分析

4.1事件傳遞流程圖

  1. 事件流程圖


    在這里插入圖片描述

IOKit.framework 為系統(tǒng)內(nèi)核的庫
SpringBoard.app 相當于手機的桌面
Source1 主要接收系統(tǒng)的消息
Source0 - UIApplication - UIWindow

  1. 從UIWindow 開始步驟悼做,見下圖
在這里插入圖片描述

比如我們在self.view 上依次添加view1疯特、view2、view3(3個view是同級關系)肛走,那么系統(tǒng)用hitTest以及pointInside時會先從view3開始便利漓雅,如果pointInside返回YES就繼續(xù)遍歷view3的subviews(如果view3沒有子視圖,那么會返回view3)朽色,如果pointInside返回NO就開始便利view2邻吞。
反序遍歷,最后一個添加的subview開始葫男。也算是一種算法優(yōu)化

4.2 HitTest 抱冷、pointInside

當我們觸控手機屏幕時系統(tǒng)便會將這一操作封裝成一個UIEvent放到事件隊列里面,然后Application從事件隊列取出這個事件梢褐,接著需要找到去響應這個事件的最佳視圖也就是Responder, 所以開始的第一步應該是找到Responder, 那么又是如何找到的呢旺遮?那就不得不引出UIView的2個方法:

  • -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
    返回視圖層級中能響應觸控點的最深視圖
  • -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
    返回視圖是否包含指定的某個點
  • 通過簡單示例代碼來驗證一下
EOCLightGrayView *grayView = [[EOCLightGrayView alloc] initWithFrame:CGRectMake(50.f, 100.f, 260.f, 200.f)];
    
    redView = [[EOCRedView alloc] initWithFrame:CGRectMake(0.f, 0.f, 120.f, 100.f)];
    
    EOCBlueView *blueView = [[EOCBlueView alloc] initWithFrame:CGRectMake(140.f, 100.f, 100.f, 100.f)];
    
    EOCYellowView *yellowView = [[EOCYellowView alloc] initWithFrame:CGRectMake(50.f, 360.f, 200.f, 200.f)];
    
    [self.view addSubview:grayView];
    [grayView addSubview:redView];
    [grayView addSubview:blueView];
    [self.view addSubview:yellowView];
在這里插入圖片描述

測試結果如下:


在這里插入圖片描述

我們可以得出結論:

  1. 點擊red,由于yellow 與 grey 同級盈咳,yellow 比 grey 后添加耿眉,所以先打印yellow,由于觸摸點不在yellow內(nèi)鱼响,打印grey鸣剪,然后遍歷grey,打印他的兩個subviews

  2. 通過在HitTest返回nil丈积,pointInside并沒有執(zhí)行筐骇,我們可以得知,pointInside調(diào)用順序你在HitTest之后的桶癣。

  3. pointInside 的 參數(shù) :(CGPoint)poinit 的值是以自身為坐標系的拥褂,判斷點是否view內(nèi)的范圍是以view自身的bounds為范圍,而非frame

  4. 如果在grey的hitTest返回[super hitTest:point event:event]牙寞,則會執(zhí)行gery.subviews的遍歷(subviews 的 hitTest 與 pointInside),grey 的 pointInside 是判斷觸摸點是否在grey的bounds內(nèi)(不準確),grey 的 hitTest 是判斷是否需要遍歷他的subviews.

  5. pointInside 只是在執(zhí)行hitTest時间雀,會在hitTest內(nèi)部調(diào)用的一個方法

  6. pointInside 只是輔助hitTest的關系

  7. hitTest是一個遞歸函數(shù)

  • 還原h(huán)itTest內(nèi)部實現(xiàn)代碼
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    ///hitTest:判斷pointInside悔详,是不是在view里?是的話惹挟,遍歷茄螃,不是的話返回nil;假設我就是點擊灰色的,返回的是自己连锯;
    NSLog(@"%s",__func__);
    
    NSArray *subViews = [[self.subviews reverseObjectEnumerator] allObjects];
    UIView *tmpView = nil;
    for (UIView *view in subViews) {
        
        CGPoint convertedPoint = [self convertPoint:point toView:view];
        if ([view pointInside:convertedPoint withEvent:event]) {
            
            tmpView = view;
            break;
            
        }
        
    }
    
    if (tmpView) {
        return tmpView;
    } else if([self pointInside:point withEvent:event]) {
        
        return self;
    } else {
        
        return nil;
        
    }
    
    
    return [self hitTest:point event:event];  //redView
    
    ///這里是hitTest的邏輯
    
    ///alpha(<=0.01)归苍、userInterActionEnabled(NO)、hidden(YES)  pointInside返回的為NO
    
}

4.3 UIRespond 與 響應鏈的組成

在這里插入圖片描述

所有視圖按照樹狀層次結構組織,每個view都有自己的superView, 包括vc的self.view:

  1. 當一個view被添加到superView上的時候, 它的nextResponder就會被指向所在controller

  2. 當vc被初始化的時候,self.view的nextResponder會被指向所在的controller
    如果當前這個view是控制器的self.view,那么控制器就是上一個響應者,如果當前這個view不是控制器的view,那么父控件就是上一個響應者)

  3. vc的nextResponder會被指向self.view的superView

  4. 最頂級的vc的nextResponder指向UIWindow

  5. UIWindow的nextResponder指向UIApplication
    這就形成了響應鏈,通過UIResponder串連起來的

touches方法實際上沒做什么,UIView繼承了它并重寫,把事件傳遞給nextResponder,相當于[self.nextResponder touchBegan:touches withEvent:event]. 當一個view沒有重寫touch事件,那么這個事件就會一直傳遞下去, 直到UIApplication. 如果重寫了touch方法,這個view響應了事件,事件就被攔截了, 它的nextResponder不會收到這個事件.

  • 響應鏈事件傳遞 向上傳遞:
  1. 如果view的控制器存在, 就傳遞給控制器,如果控制器不存在,則將其傳遞給它的父視圖.

  2. 在視圖層次結構的最頂級視圖,如果不能處理收到的事件/消息,則將事件/消息傳遞給window對象進行處理

  3. 如果window對象不處理,則將其事件/消息傳遞給UIApplication對象

  4. 如果UIApplication不處理事件/消息,則將其丟棄

  • 監(jiān)聽事件的基本流程:
  1. 當應用程序啟動以后創(chuàng)建UIApplication對象

  2. 然后啟動消息循環(huán)監(jiān)聽所有事件

  3. 當用戶觸摸屏幕的時候,消息循環(huán)監(jiān)聽到這個觸摸事件

  4. 消息循環(huán)首先把監(jiān)聽到的觸摸事件傳遞給UIApplication對象

  5. UIApplication對象再傳遞給UIWindow對象

  6. UIWindow對象再傳遞給UIWindow的根控制器rootViewController

  7. 控制器再傳遞給控制器所管理的view

  8. 控制器所管理的view在其內(nèi)部搜索看本次觸摸的點在哪個控件的范圍內(nèi)

  9. 找到某個控件以后,調(diào)用這個控件的touchBegan方法,再一次向上返回,最終返回給消息循環(huán)

  10. 消息循環(huán)知道哪個按鈕被點擊后, 在搜索這個按鈕是否注冊了對應的事件,如果注冊了,就調(diào)用這個事件處理程序.(一般就是執(zhí)行控制器中的事件處理方法)

4.4 手勢與事件關系

  1. 手勢 與 hitTest 的關系

相同上面的學習我們可以推測出运怖,手勢的響應也得必須經(jīng)過hitTest先找到視圖才能觸發(fā)(已驗證)

  1. 手勢與 觸摸事件的關系

touch事件是UIView內(nèi)部的東西拼弃,而手勢疊加上去的觸摸事件

subview會響應superview的手勢, 但是同級的subview不會響應

  1. 系統(tǒng)如何分辨手勢種類

首先我們想在手勢中調(diào)用 touches 方法必須要導入

import <UIKit/UIGestureRecognizerSubclass.h>

因為gesture繼承的是NSObject 而不是 UIRespond

通過嘗試不調(diào)用 tap手勢 的touchesBegan 摇展,發(fā)現(xiàn)tap手勢無法響應
通過嘗試調(diào)用touchesBegan 吻氧,但是不調(diào)用 pan手勢 的touchesMoved ,發(fā)現(xiàn)pan手勢無法響應
我們通過UITouch的實例咏连,可以看到里面有很多屬性盯孙,比如點擊的次數(shù),上次的位置等祟滴,結合這個屬性系統(tǒng)與touches方法就可以判斷出你使用的是什么手勢

  1. 手勢與view的touches事件的關系

首先通過觸摸事件振惰,先響應touchesBegan 以及 touchesMoved,直到手勢被識別出來垄懂,調(diào)用touchesCancelled报账,全權交給手勢處理。
但是我們可以改變這種關系

下面是系統(tǒng)的默認設置
 tapGesture.delaysTouchesBegan = NO;   
///是否延遲view的touch事件識別埠偿;如果延遲了(YES)透罢,并且手勢也識別到了,touch事件會被拋棄

 tapGesture.cancelsTouchesInView = YES;   
///識別手勢之后冠蒋,是否取消view的touch事件
// 如果為NO, touchesCancelled 不會調(diào)用羽圃,取而代之的是手勢結束后touchesEnd

4.5 手勢識別

手勢識別器 UIGestureRecognizer

簡介

UIGestureRecognizer是蘋果在iOS 3.2之后,推出的手勢識別功能抖剿。UIGestureRecognizer是一個抽象類朽寞,將觸摸事件封裝成了手勢對象,大大簡化了開發(fā)者的開發(fā)難度斩郎,同時也提升了用戶的交互體驗脑融。UIGestureRecognizer有七個子類,它們具體實現(xiàn)了不同手勢的功能缩宜。

在這里插入圖片描述

屬性方法肘迎,代理

  • 初始化甥温、添加target、移除target
//初始化方法 且 添加 target的方法
- (instancetype)initWithTarget:(nullable id)target action:(nullable SEL)action
//單獨添加target的方法
- (void)addTarget:(id)target action:(SEL)action;
//移除target的方法
- (void)removeTarget:(nullable id)target action:(nullable SEL)action;
  • 屬性和方法
//手勢的狀態(tài)
@property(nonatomic,readonly) UIGestureRecognizerState state;  
//手勢代理
@property(nullable,nonatomic,weak) id <UIGestureRecognizerDelegate> delegate;
//手勢是否有效  默認YES
@property(nonatomic, getter=isEnabled) BOOL enabled; 
//獲取手勢所在的view
@property(nullable, nonatomic,readonly) UIView *view; 
//取消view上面的touch事件響應  default  YES **下面會詳解該屬性**
@property(nonatomic) BOOL cancelsTouchesInView;       
//延遲touch事件開始 default  NO   **下面會詳解該屬性**
@property(nonatomic) BOOL delaysTouchesBegan;
//延遲touch事件結束 default  YES  **下面會詳解該屬性**
@property(nonatomic) BOOL delaysTouchesEnded;
//允許touch的類型數(shù)組妓布,**下面會詳解該屬性**
@property(nonatomic, copy) NSArray<NSNumber *> *allowedTouchTypes 
//允許按壓press的類型數(shù)組
@property(nonatomic, copy) NSArray<NSNumber *> *allowedPressTypes 
//是否只允許一種touchType 類型姻蚓,**下面會詳解該屬性**
@property (nonatomic) BOOL requiresExclusiveTouchType 
//手勢依賴(手勢互斥)方法,**下面會詳解該方法**
- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;
//獲取在傳入view的點擊位置的信息方法
- (CGPoint)locationInView:(nullable UIView*)view;                         
//獲取觸摸點數(shù)
@property(nonatomic, readonly) NSUInteger numberOfTouches;    
 //(touchIndex 是第幾個觸摸點)用來獲取多觸摸點在view上位置信息的方法                                     
- (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view; 
// 給手勢加一個名字匣沼,以方便調(diào)式(iOS11 or later可以用)
@property (nullable, nonatomic, copy) NSString *name API_AVAILABLE(ios(11.0)

先來說說requiresExclusiveTouchType這個屬性
是不是有很多人和我之前一樣狰挡,把它理解成了設置為NO,就可以同時響應幾種手勢點擊了呢释涛?
這個屬性的意思:是否同時只接受一種觸摸類型加叁,而不是是否同時只接受一種手勢。默認是YES唇撬。設置成NO它匕,它會同時響應 allowedTouchTypes 這個數(shù)組里的所有觸摸類型。這個數(shù)組里面裝的touchType類型如下:

//目前touchType有三種
typedef NS_ENUM(NSInteger, UITouchType) {
    UITouchTypeDirect,                       // 手指直接接觸屏幕
    UITouchTypeIndirect,                     // 不是手指直接接觸屏幕(例如:蘋果TV遙控設置屏幕上的按鈕)
    UITouchTypeStylus NS_AVAILABLE_IOS(9_1), // 觸控筆接觸屏幕
}

如果把requiresExclusiveTouchType設置為NO局荚,假設view上添加了tapGesture手勢超凳,你同時用手點擊和用觸控筆點擊該view,這個tapGesture手勢的方法都會響應耀态。
接下來說說cancelsTouchesInView轮傍、delaysTouchesBegan、delaysTouchesEnd這三個屬性首装。
cancelsTouchesInView 屬性默認設置為YES创夜,如果識別到了手勢,系統(tǒng)將會發(fā)送touchesCancelled:withEvent:消息仙逻,終止觸摸事件的傳遞驰吓。也就是說默認當識別到手勢時,touch事件傳遞的方法將被終止系奉,如果設置為NO檬贰,touch事件傳遞的方法仍然會被執(zhí)行。

delaysTouchesBegan 用于控制事件的開始響應的時機缺亮,"是否延遲響應觸摸事件"翁涤。設置為NO,不會延遲響應觸摸事件萌踱,如果我們設置為YES葵礼,在手勢沒有被識別失敗前,都不會給事件傳遞鏈發(fā)送消息并鸵。

delaysTouchesEnd 用于控制事件結束響應的時機鸳粉,"是否延遲結束觸摸事件",設置為NO园担,則會立馬調(diào)用touchEnd:withEvent這個方法(如果需要調(diào)用的話)届谈。設置為YES枯夜,會等待一個很短的時間,如果沒有接收到新的手勢識別任務疼约,才會發(fā)送touchesEnded消息到事件傳遞鏈卤档。

手勢依賴方法-requireGestureRecognizerToFail
用法:[A requireGestureRecognizerToFail:B] 當A蝙泼、B兩個手勢同時滿足響應手勢方法的條件時程剥,B優(yōu)先響應,A不響應汤踏。如果B不滿足條件织鲸,A滿足響應手勢方法的條件,則A響應溪胶。其實這就是一個設置響應手勢優(yōu)先級的方法搂擦。
如果一個view上添加了多個手勢對象的,默認這些手勢是互斥的哗脖,一個手勢觸發(fā)了就會默認屏蔽其他手勢動作瀑踢。比如,單擊和雙擊手勢并存時才避,如果不做處理橱夭,它就只能發(fā)送出單擊的消息。為了能夠優(yōu)先識別雙擊手勢桑逝,我們就可以用requireGestureRecognizerToFail:這個方法設置優(yōu)先響應雙擊手勢棘劣。

  • UIGestureRecognizerDelegate代理方法
//開始進行手勢識別時調(diào)用的方法,返回NO楞遏,則手勢識別失敗
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;

//手指觸摸屏幕后回調(diào)的方法茬暇,返回NO則手勢識別失敗
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldReceiveTouch:(UITouch *)touch;

//是否支持同時多個手勢觸發(fā)
//返回YES,則可以多個手勢一起觸發(fā)方法寡喝,返回NO則為互斥
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)
otherGestureRecognizer;

//下面這個兩個方法也是用來控制手勢的互斥執(zhí)行的
//這個方法返回YES糙俗,第二個手勢的優(yōu)先級高于第一個手勢
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)
otherGestureRecognizer 

//這個方法返回YES,第一個手勢的優(yōu)先級高于第二個手勢
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)
otherGestureRecognizer

子類

  • 點擊手勢——UITapGestureRecognizer

  • 捏合手勢——UIPinchGestureRecognizer

  • 旋轉(zhuǎn)手勢——UIRotationGestureRecognizer

  • 滑動手勢——UISwipeGestureRecognizer

  • 長按手勢——UILongPressGestureRecognizer

  • 平移手勢——UIPanGestureRecognzer

  • 屏幕邊緣平移手勢——UIScreenEdgePanGestureRecognzer

參考大神博客:http://www.reibang.com/p/4ad8b71246f7

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末预鬓,一起剝皮案震驚了整個濱河市巧骚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌珊皿,老刑警劉巖网缝,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蟋定,居然都是意外死亡粉臊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門驶兜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扼仲,“玉大人远寸,你說我怎么就攤上這事⊥佬祝” “怎么了驰后?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長矗愧。 經(jīng)常有香客問我灶芝,道長,這世上最難降的妖魔是什么唉韭? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任夜涕,我火速辦了婚禮,結果婚禮上属愤,老公的妹妹穿的比我還像新娘女器。我一直安慰自己,他們只是感情好住诸,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布驾胆。 她就那樣靜靜地躺著,像睡著了一般贱呐。 火紅的嫁衣襯著肌膚如雪丧诺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天吼句,我揣著相機與錄音锅必,去河邊找鬼。 笑死惕艳,一個胖子當著我的面吹牛搞隐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播远搪,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼劣纲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谁鳍?” 一聲冷哼從身側響起癞季,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎倘潜,沒想到半個月后绷柒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡涮因,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年废睦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片养泡。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡嗜湃,死狀恐怖奈应,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情购披,我是刑警寧澤杖挣,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站刚陡,受9級特大地震影響惩妇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜橘荠,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一屿附、第九天 我趴在偏房一處隱蔽的房頂上張望郎逃。 院中可真熱鬧哥童,春花似錦、人聲如沸褒翰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽优训。三九已至朵你,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間揣非,已是汗流浹背抡医。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留早敬,地道東北人忌傻。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像搞监,于是被迫代替她去往敵國和親水孩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

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

  • 重點參考鏈接: View Programming Guide for iOS https://developer....
    Kevin_Junbaozi閱讀 4,453評論 0 15
  • 在iOS開發(fā)中經(jīng)常會涉及到觸摸事件琐驴。本想自己總結一下俘种,但是遇到了這篇文章,感覺總結的已經(jīng)很到位绝淡,特此轉(zhuǎn)載宙刘。作者:L...
    WQ_UESTC閱讀 6,012評論 4 26
  • 本文主要講解iOS觸摸事件的一系列機制,涉及的問題大致包括: 觸摸事件由觸屏生成后如何傳遞到當前應用牢酵? 應用接收觸...
    baihualinxin閱讀 1,210評論 0 9
  • 前言: 按照時間順序悬包,事件的生命周期是這樣的: 事件的產(chǎn)生和傳遞(事件如何從父控件傳遞到子控件并尋找到最合適的vi...
    小蟲筆墨閱讀 1,094評論 0 14
  • 前言: 按照時間順序,事件的生命周期是這樣的: 事件的產(chǎn)生和傳遞(事件如何從父控件傳遞到子控件并尋找到最合適的vi...
    reviewThis閱讀 729評論 1 2