2014-10-29 55 views
14

我正在使用Autolayout將按鈕放在視圖上的iOS 8鍵盤上工作。
當我使用約束來更改佈局時,屏幕上的所有內容都正確顯示,但是當我想知道視圖的幀大小時,我無法獲得正確的大小。iOS Autolayout - 未設置viewDidLayoutSubviews中的幀大小

例如:我按一個鍵,鍵盤佈局會根據我的約束更改和佈置一切。然後我想知道屏幕上的任何按鈕的大小 - 我這樣做,在「viewDidLayoutSubviews」,並得到這一結果在控制檯:

2014-10-29 12:27:09.088 Keyboard[2193:60674] view did layout subviews 
2014-10-29 12:27:09.088 Keyboard[2193:60674] {{inf, inf}, {0, 0}} 

按鈕具有正確的大小和正確的位置上,而是試圖在得到它的框架的大小沒有設置。

我不得不把我的代碼放在viewDidLayoutSubviews中不工作的地方?

我發現了很多關於stackoverflow和其他websited的問題,但沒有一個覆蓋我的問題。

回答

7

是的!我自己解決了這個問題。

我不知道如果我是正確的,但是這就是我認爲:

  • viewDidLayoutSubviews得到的每一個時間稱爲當佈局正在發生變化
  • viewDidLayoutSubviews得到的調用時直接子視圖我的觀點是做了佈局,但是那個子視圖的子視圖在那個時候沒有佈局,所以你不能得到它們的大小。

我的解決方案現在是手動調用.layoutSubviews()我所有的意見其中包含我自己鍵盤上的所有按鈕。之後,我得到我想要的所有按鈕的大小。

如果我錯了,請糾正我。

+1

爲我工作,但我不知道這是否正確。 – JohnHanr 2015-01-19 02:50:12

31

我遇到了一個非常類似的問題(upvoted question),發現beeef's answer指向正確的方向。鑑於蘋果的文件說,不叫layoutSubviews()直接,我反而做了如下(其中mySubView是self.view的直接子視圖):

override func viewDidLayoutSubviews() { 
    // self.view's direct subviews are laid out. 
    // force my subview to layout its subviews: 
    self.mySubView.setNeedsLayout() 
    self.mySubView.layoutIfNeeded() 

    // here we can get the frame of subviews of mySubView 
    // and do useful things with that... 
} 

僅供參考,以我的情況mySubView是一個UIScrollView,和我需要獲取其中一個子視圖的框架,以便在視圖出現之前相應地設置contentOffset。我不確定viewDidLayoutSubviews()是否是最好的地方,但它確保了mySubView已經佈置好。

0

當訴諸DispatchQueue.asyncAfter()時,我總覺得有點骯髒,但在這種情況下感覺有保證,因爲viewDidLayoutSubviews在視圖層次結構中的所有AutoLayout調整發生之前被調用。我更喜歡它強制一個額外的同步佈局。

override func viewDidLayoutSubviews() { 
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) { [weak self] in 
     // Updated sub-subview frames can be accessed here 
     // Note - access self weakly here for the unlikely, but possible, case it was deallocated 
    } 
}