1. 程式人生 > >蘋果開發 筆記(61)recursiveDescription 方法

蘋果開發 筆記(61)recursiveDescription 方法

最近一直在疑惑為什麼有NavigationBar的情況, 我在view裡面添加了一個UIlabel, 希望這個UIlable 的偏移的位置是離NavigationBar 底部 20 點即可。
我初始化使用的方法是 根據 獲取狀態列的高度設計。然後計算他的高度

 NSInteger height = self.navigationController.navigationBar.frame.size.height+20;
self.label  = (CGRect) {0,height,200,20};
[self.view addSubView:self.label];

可是在我使用ios 6的 真機除錯發現,這個UILabel偏移得太厲害,我心想明明導航欄的高度就是44 ,再加上狀態列的20 就是 64,於是我的frame的高度值應該64+20(偏移值)就正確了。可是我真機除錯發現效果相差太大, 無論我怎樣理解都找不到問題原因。今天,我通過列印這個父類這個recursiveDescription 我一切的疑惑都解決到了。

(一些部落格也提及到這個方面的問題)。IOS6和IOS7 改變導致了一些適配的問題。剛好我的手機一直只是IOS6系統。所以今天使用這個命令解決我之前的疑惑,也瞭解到元件樹形層級關係。
注:這個方法是私有不公開 所以敲打要小心。
(lldb) po [self.view.superview recursiveDescription]

這裡寫圖片描述

可以看到在UIView 有兩個屬性 一個是父類superview,一個是子類(subviews)。父類只有一個,子類可以有多個。

IOS7 以上模擬器除錯下
我們再從日誌裡面檢視到UIViewControllerWrapperView這個類幹了什麼事? 這個類裡面frame 值是 (0 0; 375 667),再看 他的UIView 的frame (0 0; 375 667)。

在IOS 6真機 除錯下
你可以看到一個另外一個不同的資料,顯示到view其實位置在什麼地方。 同樣view 的座標是 (0 ,0) 但是它的父類起始座標就變成了(0,64)。這種情況是 導航欄+狀態列 ,而view的父類卻在(0,64)的位置。

這裡寫圖片描述

曾經有一回,我一直認為UIViewController 只有唯一個View 根物件存在,所以當我認定是這樣,但是列印後,找到層級關係,發現這些細微的地方還是有存在的。有了這個方法,對除錯真的起到很大作用。解析出為什麼在IOS6 有導航欄下,view會在導航欄下面,原因就是他的父類起始發生變化(0,64),但我們平時操作的類都是使用view 進行,然而這個列印結果卻讓我們發生一些認識的改變
這裡寫圖片描述

IOS7 以上下,UIViewControllerWrapperView 和UIView 的frame 是一樣,是全屏的。所以他們開始座標都是以(0,0)開始。

可以查閱這篇文章的列印結果得到不同情況下的frame值是如何改變。

topLayoutGuide 和 bottomLayoutGuide 的使用

@property(nonatomic,readonly,retain) id<UILayoutSupport> topLayoutGuide NS_AVAILABLE_IOS(7_0);
@property(nonatomic,readonly,retain) id<UILayoutSupport> bottomLayoutGuide NS_AVAILABLE_IOS(7_0);

在ios7 裡面有這樣兩個屬性,在xcode 進行介面整理的時候,發現一個進行約束的時候可以相容到IOS6 和IOS7的導航欄和狀態列問題操作。這個僅僅使用約束就能完成到。不需要編寫任何程式碼。topLayoutGuide 屬性提供了這個獲取導航欄和狀態列的高度和。有了這個值就可以指定約束觀察點。

需求很簡單: 建立一個UIlabel 在導航欄偏移20個點,從上面輸出列印日誌可以看看 要完成這個操作 注意一點在IOS 6裡面 父類 在導航欄下 剛好在 (0,64)的位置上,它的子類view則(0,0)。在IOS7裡面,這個發生了變化。所以可以判斷兩個版本進行

-(void) viewWillLayoutSubviews
{
   CGFloat height = 20; 
    if(IS_IOS7>6)
    {     
       if ([self respondsToSelector:@selector(topLayoutGuide)]) 
       { 
          height = self.topLayoutGuide.length +20(偏移20點完成上面的需求); 
       } 
       self.label.frame = (CGRect){0,height,200,200 };
    }
}

在XIB的使用約束完成指定操作
在xib很方便拖放元件,包括在storyboard也是一樣,很方便使用元件。有一個坑要注意是。我第一次使用這個storyboard 選定尺寸顯示的時候,被這個玩意搞糊塗了。其實一開始做元件的時候,就要求選定這個尺寸觀察。 4,4.7 3.5 也沒問題,其實這個並沒有太大關係。我們所需要做的工作對元件進行約束。 但是一旦想改這個尺寸,那麼不好意思 你的約束和佈局都全亂了。要重新來過,所以這個坑我還是遇上了。想想有了這個約束的機制,算出了一個相對位置,相對寬度,相對居中等。這些操作幫助我們做一些手機是螢幕適配工作了。