你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 詳解Xcode 6的視圖調試

詳解Xcode 6的視圖調試

編輯:IOS開發基礎

本文由遠的風景翻譯自raywenderlich,作者:Scott Berrevoets
原文:View Debugging in Xcode 6
app-view (1).jpg
開發者會經常遇到視圖或者Auto Layout約束中存在bug的情況,並且這種bug很難通過代碼發現,所以開發者很有必要熟知如何進行簡單高效的視圖調試,而Xcode 6的發布使得視圖調試變得前所未有的簡單。

開發者不用將frames打印到控制台,然後在腦海中可視化視圖的布局,現在你可以在Xcode中查看整個視圖層次。

本教程會帶你熟悉所有可以操作的不同選項。你做好寫代碼的准備了嗎?這個問題有點令人煩心,因為你根本就不想寫代碼。你可以在Xcode 6中檢查開源庫的視圖層次,了解它的編寫方法---最重要的是不用看任何代碼。

開始

本教程使用Jesse Squires 編寫的JSQMessagesViewController庫,庫的UI看起來非常熟悉,類似Messages app。

先在 GitHub project page下載源碼並解壓。

注意: 該庫使用了CocoaPods來管理和其他庫之間的依賴關系,不熟悉的話可以先看看CocoaPods tutorial。

接著在終端找到解壓項目,運行 pod install 安裝所需依賴關系。打開JSQMessages.xcworkspace並編譯,然後在iPhone5s模擬器中運行應用程序。  (可使用任意尺寸的模擬器,本教程中使用的是4英寸的模擬器,你可以選擇4英寸模擬器以便於快速了解教程內容)

注意: Live View Debugging僅支持在iOS 8上運行應用程序,不支持iOS 7,即便你用的是Xcode 6。 

點擊項目中的 Push via storyboard選項 進入與Steve Jobs 和Tim Cook消息發送界面線程,這就是你將要查看的視圖。

Screen-Shot-2015-04-07-at-12.03.28-PM-280x500.png

Even Steve Wozniak joins the fun!

回到Xcode並點擊調試欄中的Debug View Hierarchy按鈕 ,或者通過Debug\View Debugging\Capture View Hierarchy操作,效果是一樣的。

404.png

Xcode會打斷app的運行並進行調試,該操作和你使用調試欄上的的"pause"按鈕暫停app運行一樣。此外,Xcode會展示canvas(譯者注:以下簡稱"畫布")而不是代碼編輯器。Xcode在canvas上繪制了app主窗口的整個視圖層次,包括指示每個視圖邊界的細線(稱之為線框圖)。

21.png

如果往視圖層次上添加一個子視圖,也就是在當前的視圖堆棧上添加layer。由於大部分views不會疊加,所以運行app時,所有的views看起來像是大layer的一部分,下圖非常接近這種描述,不過帶著一些額外的線。

現在你所看到的是一個可視化的視圖堆棧。在canvas中點擊並拖動,會看到視圖層次的3D模型。

22.gif

你可以從上、下、左、右多個角度查看視圖層次。

745.png

注意:在嘗試的過程中,canvas可能不會像教程中展示的這樣。為確保你是在同一個頁面,請按下cmd + 6 調出Debug navigator。

在面板底部左側有兩個按鈕。如下圖所示,取消對這兩個按鈕的選定,否則會隱藏一些視圖。

23.png

探索視圖層次(Exploring the View Hierarchy)

最自然最常用的方式是從左邊開始探究3D模型,稍後教程為解釋為什麼要這麼做。向左拉動視圖層次,如下圖所示:

24.png

如果你想可視化app的構建,那麼從多個角度查看視圖層次就非常有用了。不過,在堆棧的底部(左邊)有很多空視圖,它們是什麼呢?

點擊最左邊的視圖(也就是最後邊的視圖),Xcode會對其進行高亮。畫布上方的Jump Bar(跳轉欄)更新展示一個UIWindow作為最新項目--最新項目通常指出了當前選中的項目以及其class類型。

77.png

由於該app只使用一個窗口,所以可假定位於跳轉欄前邊的UIWindow 是app的主要窗口,也就是AppDelegate的 window 屬性。

不過,似乎檢查這個圖層並沒有多大意義。那下一個視圖呢?在畫布中,點擊窗口最右邊的視圖(也就是最上邊的視圖),再看看跳轉欄(Jump Bar)看看有什麼不一樣的。UILayoutContainerView,甚至不是一個公開類。

75.png

這時候,視圖層次看起來是這樣的:

1.UINavigationTransitionView:導航控制器在這裡發生轉場行為的容器視圖。

2.UIViewControllerWrapperView: 包含view controller 的view屬性的封裝視圖。

3.UIView: view controller的最上層視圖 (與view controller的view 屬性一致)

4.JSQMessagesCollectionView: 工程使用collection view來展示所有消息。

Focusing on Views of Interest(關注與調試相關的視圖)

在調試該特定視圖層次時,頭四個視圖(從窗口開始)實際上是視覺"噪音",它們並無多大意義,會讓你分心,如果能過濾掉這些"噪音"視圖就最好不過了。

你當然可以這麼做!在畫布的右下角有一個雙滑塊兒滑桿,左右滑動滑塊可幫你暫時隱藏一些視圖,默認情況下,滑塊在滑桿的左右兩端。

79.png

將滑塊左端滑塊向右滑動一點,畫布中app的線框圖會一層層消失。將滑塊兒拖得更遠一點,UINavigationTransitionView也消失不見了。

根據需要將左端滑塊兒盡可能拖得遠一些,從而隱藏JSQMessagesCollectionView的父視圖。你的畫布看起來應該和下邊類似:

80.png

在右側,你會發現導航欄似乎有點讓人分心,但是它的的確確位於collection view的最上層,不方便查看下層布局。幸運的是你可以隱藏它。

由於你主要關於屏幕上較小的一個區域,並且導航欄上還有很多比導航欄更小的元素。這時候放大導航欄可以讓你更清楚地看到界面是如何布局的。

使用縮放控件按鈕,它是一組三個的按鈕,居中展示在畫布中。

10.png

這一組按鈕有放大"+"、縮小"-"以及將視圖重置到正常的水平的"="三種選擇,

11.png

注意:如果你使用的是觸控板,兩指捏合和縮放也能縮小和放大視圖。如果你一次性縮放過多,那麼屏幕上的內容就不能完全展示,這時候使用觸控板還是比較有用的。當然你也可以使用鼠標滑輪進行縮放。

雖然通過縮放toolbar獲得額外的細節非常不錯,但這些視圖仍緊緊地疊加在一起,要分清誰是誰並不容易。

想要解決這個問題,可以使用畫布左下角的spacing slider,向右拖動圓形滑塊兒越遠,不同同視圖之間的間距。視圖間的間距會隨著滑塊兒拖動的距離增加而變大。

13.png

在該案例中,盡可能地向右移動滑桿兒,以避免工具欄中視圖疊加。你可以試試在畫布上拖放視圖以達到理想的效果。

14.png

畫布右下角隱藏視圖的滑桿,將右端滑塊兒移至左端,直到剩下UINavigationBar。選擇最上邊的圖層,你可以使用Jump Bar來辨認每個視圖的類。首先你會看到導航項目消失了,接著是包含它們的按鈕,然後是一些私有視圖,最後是導航欄。

15.png

啊?沒有導航欄了!

注意:旋轉畫布查看3D視圖層次,如果最頂層視圖位於左側,那麼滑桿兒的左側滑塊兒依舊從堆棧底部移除視圖,現在是在右側。同樣,不管頂層視圖在左側還是右側,右側滑塊兒都從堆棧的頂部開始移除。

將滑塊兒從左側移至右側,視圖從右向左逐漸消失(反之亦然),這是有違直覺的,這也是讓頂層視圖位居右側,這種查看3D模型的方式才是最自然的方式,就是我們在教程最初提到的那一點。

不幸的是,隱藏導航欄(包含_UIBackdropView根視圖)視圖也會讓屏幕底部toolbar裡的內容消失。調整縮放度或向下移動畫布才能看到發生的變化。

由於toolbar項目是屏幕上重要的一部分,你需要查看這些內容,所以僅僅隱藏視圖直到(但不包括)剩下_UIBackdropView,導航欄堆棧看起來像是下邊這種:

16.png

More View Options(更多視圖選項)

現在已經隱藏了不相關的視圖,我們接著要從正面再看這個屏幕。你可以將3D模型拖回原位,不過有時候很難剛剛好,還好我們有其他辦法。

在3D模型的下方---縮放按鈕的左側有一組四個按鈕,從左向右數第三個按鈕是ResetViewing Area按鈕,它可以取消旋轉並從正面展示視圖層次,像在模擬器或者設備上一樣。

17.png

畫布看起來應該和下邊的一樣:

18.png

你可能注意到你在調試器中所見到的,並不全是app實際運行時的樣子。

首先,單個視圖周圍易燃有線框圖包圍,它們可以讓你查看透視圖或者沒有任何內容的視圖,不過如果你不需要細節信息,線框圖就會讓事情變得雜亂。

你可以使用View Mode按鈕進行選擇-在Reset Viewing Area按鈕的右側。點擊視圖模式按鈕,你可以選擇只查看線框圖、只查看內容或者同時查看兩者。

19.gif

如果你主要是對位置感興趣,並且不大關心視圖看起來什麼樣子,那麼線框圖是非常有用的。當你想要調試視圖的外觀時,僅展示視圖內容就非常有用了。

想要減少線框圖引起的雜亂(尤其是靠近導航欄和toolbar的地方),可將查看模式更改為Contents ,以移除所有線框圖,僅留下app的核心部分。

747.png

接下來,是從當前視圖中忽略的幾點。

當你運行app時,你將會看到文本氣泡上的標簽,指示信息發送者名稱或者信息的時間戳,以及最後一個氣泡中Golden Gate Bridge的圖片。但是調試器並不會展示這些標簽和圖片。想要解決這個問題,可查看畫布上中間一組按鈕的第一個,可展示或者隱藏省略掉的視圖。這些視圖的clipsToBounds屬性設置為了YES。

78.png

這是標簽相關的,大概由於較長的名字和日期不應當延伸到標簽的界限之外。這一點同樣應用於圖片,圖片使用圓角半徑並剪切以生成圓角圖片。點擊該按鈕,你會注意到這些視圖將不再出現在Xcode中。

79.png

注意:你可能注意到可視項目周圍仍有線框圖,如果是這種情況,使用你先前使用的View Mode按鈕

打開和關閉線框圖,問題即可解決。

你已經都了解了:在Xcode中近乎完美地復制了視圖層次。

802.png

So easy!

Inspecting Views(查看視圖)

已經了解了最重要的部分,現在看看這些不同視圖的布局。

你已經知道了collection view如何讓這些視圖聚集在一起,但是如果能看到這些不同元素的整體結構就更好了。當然可以啦!

按下cmd + 6 調出Debug navigator,和其他調試會話一樣,Debug navigator提供了當前會話的文本信息。對於視圖調試來說,這意味著Xcode提供了所有窗口中視圖的視圖樹。展開Debug navigator的視圖樹後是這個樣子的:

76.png

注意:在Debug navigator的底部,你會看到一個選項可以控制在視圖樹中展示哪種類型的項目。蘋果的文檔表示左邊的按鈕將系統視圖實現的私有元素過濾出來,不過這個按鈕在Xcode 6.2中似乎不起作用。

右邊按鈕可隱藏那些將其 hidden 屬性設置為YES的視圖,並且搜索欄僅展示匹配搜索條件的視圖和約束。

出於本教程的目的,取消對這兩個按鈕的選擇,並且不使用任何搜索過濾。

這是個不錯的而開始。展開最後一個JSQMessagesCollectionViewCellOutgoing,它只有一個子視圖UIView。如果你以前使用過collection view,那你應該知道這個是講得通的,因為任何UICollectionViewCell都有一個包含cell內容的contentView 屬性。

點擊但不要展開-將鼠標放在Debug navigator的UIView 上,你會看到Xcode已經在畫布上對其高亮,這樣你就准確知道它在屏幕的什麼地方。

73.png

想要真正了解iOS如何放置該cell,可使用cmd + option + 4打開Size Inspector,該導航器的頂部形象化了視圖的邊界、位置以及錨點。

72.png

不過,真正有趣的部分是應用於該視圖的Auto Layout約束列表。你可以立刻將cell的內容視圖的寬和高分別設定為312 point和170 point,並將其居中。封閉的cell同樣是312*170 point,所以內容視圖占據了整個cell。下邊用灰色顯示的約束表示它們是指出視圖和其子視圖之間關系的約束。

想了解一個特定約束的更多細節,首先要展開視圖樹中的視圖,然後展開Constraints項目。你將會看到和Size navigator中一樣的約束列表。

722.png

點擊第一個約束(self.midX的約束),並通過cmd + option + 3切換至Object inspector。你會看到一個約束概覽。編輯約束時,這一點非常類似於Interface Builder。

721.png

除了尺寸和約束信息,你還會看到Object Inspector中特定視圖的其他信息。回到Debug navigator,展開視圖樹中的UIView ,你會到它有3個JSQMessageLabel和兩個UIView。選中第一個JSQMessageLabel(帶有時間戳的那個),並打開Object Inspector。

029.png

第一個部分展示了對象的類名稱和內存地址,第二部分展示了對象的多個公有屬性的值。

從圖中看出,標簽文本的顏色是無alpha 的0.67灰,字體大小是12pt。

針對它們如何被可視化,其他類也有一些有用的信息。回到Debug navigator,展開cell的根UIView 中的第二個UIView,你會看到一個UIImageView。

710.png

從視圖樹中選擇image view,並查看Object inspector。

030.png

你正查看的是展示用戶頭像的視圖-在該例子中是作者的首字母JSQ,你會看到常規圖片、便利的貼有標簽的圖片、較暗的圖片以及被標記的高亮,這些將在用戶點擊cell時展示。

在cell的根視圖中,JSQMessageLabel的其他兩個實例當前還沒有文本,但它們被用於即將進來的消息發送者的名字和消息發送失敗時的錯誤信息。

怎麼樣,在Xcode中調試視圖非常簡單吧,繼續運行該app,點擊Debug bar上的"Continue"按鈕,或者執行Debug\Continue,就像你在常規調試中那樣。

Live Modifications(實時調整)

現在你已經了解了使用Xcode 6進行視圖調試的基礎支持,接下來將你所學應用到一個小小的實驗中:只使用調試器,確保你在本教程中使用的collection view的垂直滾動指示器為red。

你可以從以下兩點開始:

1.由於視圖調試和其他調試部分非常像,你可以在終端使用expr 和其他命令,但是需要重新運行項目才能看出所做的變化。更多關於這些命令的信息,請查看debugging apps in Xcode教程。

2.由於Objective-C中的指針僅僅是內存地址,所以當你發送對象時,你僅僅發送了一個內存地址。這同樣適合於調試器,所以類似po 0x123456abcdef這樣的命令會打印出內存地址中的對象描述。

多做幾次嘗試,如果出現問題,可嘗試以下解決方案:

首先要確保將視圖模式設置為"Contents"

031.png

在Debug navigator中,展開collection view的視圖樹,以便清楚知道視圖的子視圖。

032.png

collection view的最後視圖是兩個UIImageView實例,是水平方向和垂直方向上的滾動指示器。點擊第二個,你會看到水平方向上的指示器在畫布中被高亮。

033.png

從Object inspector中復制圖片視圖的內存地址。

034.png

在這個例子中,滾動指示器的內存地址是0x7fde6c484640。需要做的是給該地址中的對象發送一個setBackgroundColor:信息可將滾動指示器著色。可使用以下代碼:

expr (void)[0x7fde6c484640 setBackgroundColor:[UIColor redColor]]

繼續運行該應用程序,在滾動collection view時,滾動指示器變成了紅色。

祝賀你,你已經了解了使用Xcode 6進行視圖調試的基本內容。

Old School Debugging(保守調試)

實時調試讓使用Xcode 6進行視圖調試變得非常簡單,但並不意味你之前常用的調試方法已經沒有用武之地了。事實上,除了視圖調試外,iOS 8引入了一個非常受歡迎的技巧: _printHierarchy.

注意:你已經了解了Xcode 6視圖調試的基本內容,所以如果你不喜歡可以直接跳過這個章節。不過如果你非常癡迷一些便捷的舊的技術,那不要錯過這個。

打印View Controller Hierarchy

_printHierarchy是 UIViewController 的一個私有方法,你可以用它將view controller 層次打印到控制台。編譯並運行,選中Push via storyboard,然後點擊Debug bar上的"pause"按鈕。

在終端打出以下內容並重新運行:

po [[[[UIApplication sharedApplication] keyWindow] rootViewController] _printHierarchy]

得到類似下面的內容:
035.png

這告訴你UINavigationController的第一個視圖控制器是一個TableViewController,你可以選擇如何推出控制器。第二個view controller是DemoMessagesViewController,或者你已經調試過的view controller。

這個例子似乎不怎麼令人興奮,但如果你的導航控制器中有幾個view controller,或者彈出視圖中有tab bar控制器,那麼想要弄清楚這些view controller如何工作, 這個功能就非常有用了。

Printing the View Hierarchy(打印視圖層次)

如果你更喜歡文本化的視圖層次,那你可以使用UIView舊的私有recursiveDescription。這個方法打印出來的視圖層次非常類似於上邊描述的view controller層次。

打開Views\JSQMessagesCollectionViewCellOutgoing.m 並在awakeFromNib中添加一個斷點。

036.png

編譯並運行,然後選擇Push via Storyboard。調試器有問題了,因為加載了JSQMessagesCollectionViewCellOutgoing。現在在控制台輸入以下代碼:

po [self.contentView recursiveDescription]

這將打印出 JSQMessagesCollectionViewCellOutgoing的contentView層次, 看起來像這樣:

037.png

這是基本的,但可以幫你調試iOS 8之前的視圖層次。

Using debugQuickLookObject(使用debugQuickLookObject)

最後,Xcode5.1引入了Debug Quick Look功能。如果你已經做好了調試的准備,但不大想知道某段代碼如何實現對象的特定外觀,那麼這時候這個功能就非常有用了。

你的自定義類可以實現debugQuickLookObject方法,並返回任何由Xcode展示的內容。此外,如果你已經正進行調試,並且已經有了想要查看的對象,你可以使用快速查看功能,並且Xcode會以可視化形式表示對象。

比如,NSURL對 debugQuickLookObject的實現返回了一個帶有URL 的UIWebView,你可以真實看到URL背後的東西。

關於使用Quick Look調試的更多信息,請查看相關文檔。

下一步

以上是關於實時調試的內容,它是一個可以幫助節省大量時間的工具,非常好用。

如果你想尋找一些更高級、功能更全面的工具,可以試試Reveal(付費),它要比Xcode的視圖調試強大很多。你可以查看我們相關主題的Tech Talk。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved