iOS自定義控件教程(二)關于響應鏈的那些事

iOS自定義控件教程(一)UIKit入門痢掠,布局入門
iOS自定義控件教程(二)響應鏈原理
iOS自定義控件教程(三)觸摸事件和簡單動畫
iOS自定義控件教程(四)Target-Action響應模式

上一次我們一起做一個多段選擇的自定義控件叔壤,順便學習UIView的基本屬性和方法试浙。在iOS自定義控件教程(一)中我們完成了UILabel布局的工作匆篓,接下來我們一起研究一下觸摸響應鏈原理惨奕。
最終實現(xiàn)的效果:Github下載源碼

鏈式響應原理

先簡單普及一下響應鏈原理火架,我們可以簡單地認為iPhone屏幕就是一個容器,我們看到的各種控件(UIView和UIView子類)都是屏幕(UIWindow)這個容器中的子容器涝焙,最外層的容器是應用委托(AppDelegate)的屬性keyWindow卑笨,其實UIWindow也是UIView的子類。

這些容器的相互關系仑撞,就是我們最早學數(shù)據(jù)結(jié)構(gòu)接觸的多叉樹關系赤兴,keyWindow就是這棵樹的Root,其它它的子View都是分支隧哮。例如上面的例子桶良,我們用xcode進行調(diào)試可以得到下圖。注意在調(diào)試過程中沮翔,才有這排功能:

12.png

得到下面的層級結(jié)構(gòu)

屏幕快照 2016-01-04 11.13.53.png

在我們的Demo里面陨帆,總共有兩個XXXSegmentView,第一個XXXSegmentView有四個子UILabel,而他的父View是當前ViewContoller的主View疲牵,一個背景是純白色的全屏View承二。

觸摸事件被iPhone硬件接收到時,一個鏈式的觸摸信號就被開啟了纲爸。最先接收到觸摸事件的是Root亥鸠,也就是我們應用程序的keyWindowkeyWindow再將觸摸事件傳遞給它的一級子View們识啦。這個傳遞過程不需要開發(fā)者用代碼實現(xiàn)负蚊,如果開發(fā)者有需要重寫傳遞,需要使用的是UIView- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;方法颓哮。

這個方法返回的UIView家妆,就是父View決定讓哪個孩子作為這個觸摸的響應View。這樣冕茅,觸摸事件就不斷往下級傳遞伤极,對應的View才能根據(jù)觸摸事件改變樣式。

新人在開發(fā)時嵌赠,經(jīng)常會遇到不響應觸摸的情況塑荒。有兩種常見的可能打斷觸摸鏈

1. 目標View到Root的分支中熄赡,有View沒有開啟觸摸事件姜挺,打斷了響應鏈傳遞。

這里需要知道UIView有一個基本屬性叫做userInteractionEnabled彼硫,這個屬性為YES時才能響應觸摸事件炊豪。所以檢查一下分支中是否有View的觸摸開關被關閉。例如拧篮,UIImageView這個展示圖片的類词渤,默認就是不響應觸摸鏈的,如果你需要繼承它寫一個新View串绩,并且需要觸摸缺虐,或者給他添加了需要觸摸的子View,請修改他的userInteractionEnabled屬性礁凡。

2. 目標View的觸摸事件高氮,因為層級關系被上層覆蓋的View劫走,哪怕這個View可能是透明的

根據(jù)鏈式響應原理顷牌,父View會將觸摸鏈傳給符合相應條件剪芍,并且層級關系最上層的View,所以下層的View接收不到觸摸事件窟蓝,遇到這種情況罪裹,你可以根據(jù)需要進行處理。如果覆蓋在上層View層級順序有誤,通過調(diào)用他們父View的兩個方法可以輕松交換他們層級覆蓋關系状共。

- (void)bringSubviewToFront:(UIView *)view;
- (void)sendSubviewToBack:(UIView *)view;

如果上層View就是要放在上面套耕,那就關掉上層View的響應鏈,userInteractionEnabled設為NO峡继,這樣父View在進行hitTest時就會拋棄這個View箍铲,選擇層級更低的View傳遞。

關于透明

這里請注意UIView的幾個不同的屬性鬓椭。

backgroundColor 背景顏色颠猴,UIColor類
alpha 顏色中的alpha通道值,這個值范圍0-1小染,等于0時完全透明翘瓮,等于1時,完全不透明
hidden BOOL型裤翩,是否隱藏

這三個屬性资盅,都可以實現(xiàn)UIView隱身的效果。例如一個空的UIView踊赠,backgroundColor設為[UIColor clearColor]時呵扛,背景色是透明的;alpha設為0時筐带,UIView也是透明的今穿;hidden設為YES時,UIView同樣不可見伦籍。

但他們的區(qū)別也很明顯蓝晒,backgroundColor屬性的修改,不影響子View帖鸦,所以子View不會因為父View的backgroundColor設為[UIColor clearColor]而隱藏芝薇,同時,父View同樣響應觸摸鏈作儿。

而alpha值則不同洛二,渲染時alpha值時一個疊加屬性,例如父View透明度為0.5攻锰,子View透明度為0.5晾嘶,這時渲染出來的真實效果,子View的透明的應該為0.5*0.5 = 0.25口注,所以當父View的alpha為0時变擒,子View也是完全不可見的。另外寝志,alpha為0的View娇斑,是不響應觸摸鏈的策添。

最后這個hidden屬性,直接從根源毫缆,決定要不要渲染這個View唯竹,不像alpha屬性,是不需要渲染時計算最終的渲染效果的苦丁,因為這個屬性為YES時浸颓,根本不進行渲染,所以渲染鏈都斷了旺拉,子View也不會渲染了产上,更不會響應觸摸了。

響應鏈hitTest的三個條件蛾狗,就是userInteractionEnabled = YES晋涣,并且alpha != 0, 且hidden = NO。

小結(jié)

樹型結(jié)構(gòu)沉桌,既是UIView的觸摸響應結(jié)構(gòu)谢鹊,也是渲染鏈結(jié)構(gòu),觸摸鏈通過下面四個方法傳遞留凭,UIViewUIResponder的子類佃扼,下面四個方法是觸摸鏈傳遞的會調(diào)用的方法。分別對應開始蔼夜,移動兼耀,結(jié)束取消四種狀態(tài)挎扰。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(nullable NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;```

渲染樹型結(jié)構(gòu)要更加簡單一點翠订,調(diào)用的是`- (void)setNeedsDisplay;`方法,也就是在父View的setNeedsDisplay方法中遵倦,調(diào)用子View的setNeedsDisplay方法,這個方法會通知View在下一個cpu時間里官撼,進行重新渲染梧躺,也就是調(diào)用他們的`- (void)drawRect:(CGRect)rect;`方法實現(xiàn)繪制。

但是自從手勢(UIGesture)加入之后傲绣,觸摸鏈開發(fā)用的越來越少掠哥,但我們的[Demo](https://github.com/zsy78191/XXXSegmentView)還是使用了簡單的觸摸鏈。后面的章節(jié)我們將介紹功能更為便捷和強大手勢(UIGesture)功能秃诵。

[iOS自定義控件教程(一)UIKit入門续搀,布局入門](http://www.reibang.com/p/fd495346402f)
[iOS自定義控件教程(二)響應鏈原理](http://www.reibang.com/p/b3ce217eca5d)
[iOS自定義控件教程(三)觸摸事件和簡單動畫](http://www.reibang.com/p/58d9afb2b3d0)
[iOS自定義控件教程(四)Target-Action響應模式](http://www.reibang.com/p/6ac4ebe84e60)
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市菠净,隨后出現(xiàn)的幾起案子禁舷,更是在濱河造成了極大的恐慌彪杉,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牵咙,死亡現(xiàn)場離奇詭異派近,居然都是意外死亡,警方通過查閱死者的電腦和手機洁桌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門渴丸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人另凌,你說我怎么就攤上這事谱轨。” “怎么了吠谢?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵碟嘴,是天一觀的道長。 經(jīng)常有香客問我囊卜,道長娜扇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任栅组,我火速辦了婚禮雀瓢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘玉掸。我一直安慰自己刃麸,他們只是感情好,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布司浪。 她就那樣靜靜地躺著泊业,像睡著了一般。 火紅的嫁衣襯著肌膚如雪啊易。 梳的紋絲不亂的頭發(fā)上吁伺,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音租谈,去河邊找鬼篮奄。 笑死,一個胖子當著我的面吹牛割去,可吹牛的內(nèi)容都是我干的窟却。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼呻逆,長吁一口氣:“原來是場噩夢啊……” “哼夸赫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起咖城,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤茬腿,失蹤者是張志新(化名)和其女友劉穎呼奢,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體滓彰,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡控妻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了揭绑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弓候。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖他匪,靈堂內(nèi)的尸體忽然破棺而出菇存,到底是詐尸還是另有隱情,我是刑警寧澤邦蜜,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布依鸥,位于F島的核電站,受9級特大地震影響悼沈,放射性物質(zhì)發(fā)生泄漏贱迟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一絮供、第九天 我趴在偏房一處隱蔽的房頂上張望衣吠。 院中可真熱鬧,春花似錦壤靶、人聲如沸缚俏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忧换。三九已至,卻和暖如春向拆,著一層夾襖步出監(jiān)牢的瞬間亚茬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工亲铡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留才写,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓奖蔓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親讹堤。 傳聞我的和親對象是個殘疾皇子吆鹤,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,504評論 25 707
  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫、插件洲守、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,024評論 4 62
  • 《神奇動物在哪里》票房口碑都炸裂了疑务。 上映5天3.43億沾凄,快趕上《潘金蓮》12天的票房。 豆瓣評分8.1知允,跟《哈利...
    Sir電影閱讀 1,527評論 2 21
  • (一) 遇見赤司的那一天撒蟀,不,或者說是被赤司找到的那一天温鸽,他正在天臺上看輕小說保屯。陽光淡淡地灑在他的腿上,白色的頭發(fā)...
    叫我國王閱讀 1,409評論 0 1
  • 曾說在深夜里一次次地翻看她的心事 曾說將所有的時間都用來想念她 曾說沒有她在的城市你不能入眠 曾說要和她如何同甘共...
    孤銘調(diào)漁閱讀 319評論 4 1