AASubviews - Automatic arrangement subviews

自動排列子視圖

演示圖

調用說明:

只需引入 AASubviews.h 后,調用下面的方法即可:

+ (void)superview:(UIView *)superview subviews:(NSArray *)subviews;

使用場景:

如果你使用 frame 來布局,這是一個很方便的工具。場景是這樣的,一個頁面由多個不同的展示元素組成,考慮到可維護性和擴展性,這些元素可以劃分成從上至下排列的多個分組,一個分組就是一個自定義的 subview ,每個 subview 實現各自內部的展示邏輯,并且有以下特點:

  • subview 的高度可能變化;
  • subview 也可能突然隱藏或顯示;
  • 由于以上兩點,superview 的高度也會跟著變化;
  • subview 的排列順序可能變化。

演示例子:

例如需求是展示某個商家的詳情頁,對于酒店(Hotel)類型商家是下面這樣展示的,并且,為了方便管理,從上至下劃分為以下幾個部分:

例子

還有交互上是這樣的:點擊“關閉”按鈕會隱藏 DemoAdView,點擊“展開”會使 DemoDescView 變高,點擊“重置”會使所有 view 重置一遍。并且對于商店(Shop)類型的商家是有不同的展示方式。

AASubViews 可以很方便的管理這種變化。

DemoHeaderView *headerView = [DemoHeaderView createViewFromXib];
DemoNameView *nameView = [DemoNameView createViewFromXib];
DemoAdView *adView = [DemoAdView createViewFromXib];
DemoDescView *descView = [DemoDescView createViewFromXib];
DemoCommentView *commentView = [DemoCommentView createViewFromXib];

NSArray *subviews = nil;
if (self.type == DemoTypeHotel) {
    subviews = @[headerView, nameView, adView, descView, commentView];
} else {
    subviews = @[adView, nameView, descView, commentView];
}

[AASubviews superview:self.scrollView subviews:subviews];

要查看更詳細的代碼請打開工程。

原理分析:

從上至下排列 subviews,使用 KVO 原理檢測 subviewframehidden 變化,從而自動調整布局。

難點是,如果只是簡單利用 KVOsuperview 來觀察 subview 的變化,會有很多問題,例如:

  1. 如果重復 addObserver 會多次觸發 observeValueForKeyPath:ofObject:change:context 方法;
  2. 如果重復 removeObserver 會導致閃退;
  3. 如果被觀察者釋放了而還沒有 removeObserver 的話,也會導致閃退,模擬器不會發生,但是真機會發生;
  4. superview 觀察 subview ,實現 observeValueForKeyPath:ofObject:change:context 方法,最初想到有兩種方式,第一種是自定義一個 UIView 的子類,所有的 superview 繼承于這個類,這種方式改動太大了,不可取;第二種是用 category 的方式實現這個方法,這種方式會影響到整個工程所有的 view ,這種方式也不太好。

為了解決問題 1 和 2,可以每個 subview 做一個標記是否被觀察了。為了解決問題 3 和 4,可以引入一個專門觀察 subview 的類 AAObserver,然后 superview 持有這個類的實例。

以下是對象的引用關系,實線代表強引用,虛線代表弱引用:

引用關系

addSubview 的時候 addObserver,當 removeFromSuperview 的時候 removeObserver。但是當 controller 退出時 superview 自動釋放時,導致 subviews 也會自動 removeFromSuperview, 因為我們無法獲取 removeFromSuperview 的回調,這時候我們怎么 removeObserver 呢?看上面的引用關系圖,因為 observer 是對 subviews 強引用的,所以 observer 的釋放肯定在 subviews 的釋放之前, superview 釋放會導致 observer 釋放,我們可以在 observiewdealloc 方法里做 removeObserver。 這就巧妙地解決了沒移除觀察者的問題。

github地址:https://github.com/qhd/AASubviews

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 概述 UIView或者它的子類知道怎樣將自己繪制在一個矩形區域中。我們app所有可視的的界面來自于視圖。創建和配置...
    smalldu閱讀 900評論 0 6
  • iOS9 - UIView 子視圖 & 父視圖 今天主要研究了一下關于UIView章節的內容,發現以前對UIVie...
    Jeavil_Tang閱讀 380評論 0 5
  • View簡介 一個view可以從nib生成,也可以在代碼中創建。View hierarchy 是主要的view組織...
    Felix_Smile閱讀 604評論 0 0
  • 你可以下載the project source from the end of part 1與我們共同來探索 這是...
    木易林1閱讀 450評論 0 0
  • 今天要分享的是我讀NVC的一點點心得,從最初剛剛走出校園追張德芬每一本心靈成長的書,具體到一個個心理學分...
    靜禾530閱讀 375評論 0 2