你好,歡迎來到IOS教程網

 Ios教程網 >> IOS訊息 >> 關於IOS >> 淺談iOS調試技巧的實際應用(二) UI篇

淺談iOS調試技巧的實際應用(二) UI篇

編輯:關於IOS

做iOS開發, 大部分的工作跟UI相關,而分析UI最重要的就是分析UI的Hierarchy,這篇就是圍繞View Hierarchy來詳細介紹UI相關的調試技巧。

  獲取Hierarchy   巧婦難為無米之炊,首先我們得得到Hierarchy,方法是調用某個UIView對象或其子類的recursiveDescription方法。     recursiveDescription方法是UIView的私有方法。蘋果未公開該方法。常用的的場合是, 在任意斷點處執行   po [[[UIApplication sharedApplication] keyWindow] recursiveDescription] 或 po [oneView recursiveDescription]   該方法將遞歸打印該View的所有子View的層次關系,效果如下圖:            通過Hierarchy能解決哪些問題? 可用在哪些場景?       場景1: 獲取當前正在顯示的是哪個頁面(ViewController)?         好吧, 同事在很專心的思索某個問題, 我不忍心打擾他,我想知道他的VC是什麼, 做了什麼事情?或者想知道某個問題它是如何處理的。           這時, 你先在模擬器裡定位到他的頁面, 然後pause program,再在控制台打印當前keyWindow的Hierarchy,然後從輸出信息裡, 從按照等級從高到低(將View前的“|”的數量定義為該View的等級,越少等級越高), 然後同一等級下從下往上找。因為,在打印信息裡,在同一層級下,越往下的View,zOrder越高。zOrder高的View當然會蓋住zOrder低的View。           以上圖為例, 你發現<UIView: 0xa1769c0...>就是你要找的View。因為前面的都是系統的View。它會將你包裹起來做其他事情。           好了,View知道了, 那VC呢?           對象與對象之間的關系在某種程度上可以分為3種:1.互不相知, 2.單向引用, 3,雙向引用。後面2種有點像鏈表。我們都知道通過VC的view屬性就可以找到View了。但是,好像從來沒有過通過view找到它的VC的經驗?對吧。但是,也許, 你會猜,View應該也會記住它的VC是誰吧。是的。 事實確實如此。                      如圖(UIView的.h文件), 你發現你找到證據了,VC是view的一個代理,對的, 因為View有時候需要讓VC去做一些事情。 但是,這只是結構體中的一個變量了。你不能通過給對象發送消息來獲取這個值啊。因為沒有這個方法。 那怎麼辦呢? 對了。 這時OC Runtime的KVO機制就可以發揮作用了。   [oneView ValueForKey:@"_viewDelegate"]             上面這個方法就可以獲取view的VC是誰了。               除了上面KVO的方法?還有其他方法嗎?答案是:有的。           如果你了解UI的事件傳遞機制。你會知道消息會一直從hitTestView一直往上forward, 直到UIApplication為止。這個工作是由基類UIResponder完成的。當一個Responder對象不對事件處理時, 它會調用nextResponder方法找到它的下一個對象, 然後丟給它處理。           好了。如果一個View有它的VC, 按照事件傳遞機制, 它的nextResponder必定是VC。對了,如此問題就解決了。 調用View的nextResponder就一定能找到它的VC是誰。是不是很簡單呢?   [oneView nextResponder]           場景2: 為什麼我的視圖沒顯示呢?或者在某個時候不見了呢?         這個問題比較復雜。因為View的很多屬性都會影響視圖的顯示。解決問題的方法如下:            1. 自身原因             frame:有可能origion映射到Window上時,已經超出Window的邊界了。(可以通過UIView的convert方法獲取)                 有可能你的width或者height中有一個為0.             hidden: 有可能某個時候hidden屬性被置為YES。             alpha:有可能某個時候alpha屬性被置為0.            2. superView的原因             也許你的view根本沒add到superView上,或者某個時候被移除。也許是由於superView的上述“自身原因”,也許是superView的superView... 。                        幸好,frame屬性在Hierarchy信息中被打出, 如果hidden屬性為YES,alpha為0, Hierarchy會特意打印出來。所以, 基於Hierarchy你就可以分析某個試圖為什麼沒有正確顯示的原因。         場景3: 為什麼我的視圖(通過UIControll或者加UIGesture)點下去沒反應?         這個問題很復雜,有可能它不是hitTestView, 有可能消息被UIGesture優先捕獲了。這裡牽涉到消息機制, 暫時不在這裡說明。           但是, 下面可以針對hitTestView這個原因來進行分析。           如果它不被確定為hitTestView。 那麼           1.自身原因             frame: 有可能你的width或者height為0(如果一個視圖的clipsToBounds為NO時,有可能他的frame是空,但是依然能顯示出來。例如UIImageView),此時hitTest方法不能判定該View能相應事件。                 有可能自身的frame超出superView的frame。 那麼超出部分的事件將不會將hitTestView判定給該View。這個問題比較隱蔽。也會經常遇到。             userInteractionEnabled: 為NO時,不能響應事件。             Hidden:為YES時,不能響應事件。           2.superView的原因             superView的上述“自身原因”也會影響到子View響應事件。           類似場景2. 上面的問題也可以通過查看打印的Hierarchy分析。           基於Hierarchy的UI調試方法還有通過第三方工具, 例如Hierarchy Viewer可視化工具等。
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved