2013-03-26 58 views
8

我遇到一個非常奇怪的崩潰,這裏是回溯。奇怪的崩潰時解僱視圖控制器,自動佈局的責任?

* thread #1: tid = 0x2403, 0x3379516c CoreFoundation`CFHash + 8, stop reason = EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xdefe) 
    frame #0: 0x3379516c CoreFoundation`CFHash + 8 
    frame #1: 0x33797a9c CoreFoundation`CFBasicHashRemoveValue + 1408 
    frame #2: 0x337974ee CoreFoundation`CFDictionaryRemoveValue + 166 
    frame #3: 0x3420988e Foundation`-[NSISEngine removeConstraintWithMarker:] + 562 
    frame #4: 0x34211dbe Foundation`-[NSLayoutConstraint _removeFromEngine:] + 230 
    frame #5: 0x35a954ec UIKit`-[UIView(UIConstraintBasedLayout) _layoutEngine_willRemoveLayoutConstraint:] + 44 
    frame #6: 0x358488fc UIKit`__48-[UIScrollView _setAutomaticContentConstraints:]_block_invoke_0 + 148 
    frame #7: 0x34208882 Foundation`-[NSISEngine withAutomaticOptimizationDisabled:] + 166 
    frame #8: 0x35848838 UIKit`-[UIScrollView _setAutomaticContentConstraints:] + 116 
    frame #9: 0x35848e6c UIKit`-[UIScrollView _rememberDependentConstraint:] + 112 
    frame #10: 0x35a9e3ae UIKit`___updateViewDependenciesForConstraint_block_invoke_0 + 30 
    frame #11: 0x35a954ba UIKit`_updateViewDependenciesForConstraint + 202 
    frame #12: 0x35a953da UIKit`-[UIView(UIConstraintBasedLayout) _layoutEngine_didAddLayoutConstraint:roundingAdjustment:mutuallyExclusiveConstraints:] + 154 
    frame #13: 0x35a95534 UIKit`-[UIView(UIConstraintBasedLayout) _tryToAddConstraintWithoutUpdatingConstraintsArray:roundingAdjustment:mutuallyExclusiveConstraints:] + 36 
    frame #14: 0x3567c2e0 UIKit`-[UIView(Internal) _didMoveFromWindow:toWindow:] + 376 
    frame #15: 0x356d34fe UIKit`-[UIScrollView _didMoveFromWindow:toWindow:] + 50 
    frame #16: 0x3567c5c6 UIKit`-[UIView(Internal) _didMoveFromWindow:toWindow:] + 1118 
    frame #17: 0x35676e52 UIKit`-[UIView(Hierarchy) _postMovedFromSuperview:] + 138 
    frame #18: 0x3565e7dc UIKit`-[UIView(Internal) _addSubview:positioned:relativeTo:] + 1300 
    frame #19: 0x3565e2c2 UIKit`-[UIView(Hierarchy) addSubview:] + 30 
    frame #20: 0x356f68e8 UIKit`-[UITransitionView transition:fromView:toView:removeFromView:] + 972 
    frame #21: 0x35937618 UIKit`__91-[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:]_block_invoke_0238 + 388 
    frame #22: 0x357499b8 UIKit`-[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:] + 4824 
    frame #23: 0x357b9814 UIKit`-[UIViewController _dismissViewControllerWithTransition:from:completion:] + 1708 
    frame #24: 0x357057c4 UIKit`-[UIViewController dismissViewControllerWithTransition:completion:] + 912 
    frame #25: 0x000ccd40 Capture`-[INFTagSearchViewController cancelButtonTouched:](self=0x1f09ed50, _cmd=0x001b9d5f, sender=0x1e0265c0) + 76 at INFTagSearchViewController.m:48 
    frame #26: 0x357470c4 UIKit`-[UIApplication sendAction:to:from:forEvent:] + 72 
    frame #27: 0x35747076 UIKit`-[UIApplication sendAction:toTarget:fromSender:forEvent:] + 30 
    frame #28: 0x35747054 UIKit`-[UIControl sendAction:to:forEvent:] + 44 
    frame #29: 0x3574690a UIKit`-[UIControl(Internal) _sendActionsForEvents:withEvent:] + 502 
    frame #30: 0x35746e00 UIKit`-[UIControl touchesEnded:withEvent:] + 488 
    frame #31: 0x3566f5f0 UIKit`-[UIWindow _sendTouchesForEvent:] + 524 
    frame #32: 0x3565c800 UIKit`-[UIApplication sendEvent:] + 380 
    frame #33: 0x3565c11a UIKit`_UIApplicationHandleEvent + 6154 
    frame #34: 0x373655a2 GraphicsServices`_PurpleEventCallback + 590 
    frame #35: 0x373651d2 GraphicsServices`PurpleEventCallback + 34 
    frame #36: 0x33829172 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 34 
    frame #37: 0x33829116 CoreFoundation`__CFRunLoopDoSource1 + 138 
    frame #38: 0x33827f98 CoreFoundation`__CFRunLoopRun + 1384 
    frame #39: 0x3379aebc CoreFoundation`CFRunLoopRunSpecific + 356 
    frame #40: 0x3379ad48 CoreFoundation`CFRunLoopRunInMode + 104 
    frame #41: 0x373642ea GraphicsServices`GSEventRunModal + 74 
    frame #42: 0x356b0300 UIKit`UIApplicationMain + 1120 
    frame #43: 0x000a297c Capture`main(argc=1, argv=0x2fd60cfc) + 116 at main.m:16 
    frame #44: 0x3bb2bb20 libdyld.dylib`start + 4 

你會注意到架25只叫我的代碼做,這是cancelButtonTouched它看起來像。

- (IBAction)cancelButtonTouched:(id)sender { 
    [self dismissViewControllerAnimated:YES completion:nil]; 
} 

我很茫然,什麼是怎麼回事,我從來沒有過這樣的前一個問題,基於該系統調用它似乎是一個自動佈局問題。我證實在崩潰發生之前viewWillApper在呈現視圖控制器上被調用,所以我認爲它是呈現視圖的佈局期間的發佈。

關於如何將此問題縮小到特定佈局約束的任何想法?還是其他想法?

這是可以在一些設備上重現,而在其他設備上,它很少會發生。所以它是間歇性的。

更新

截圖斷點。

enter image description here

更新2

所以它肯定是解僱的presentingViewController,駁回兩個層面的問題深([self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil])工作正常,但顯然不是理想的結果,我只是想回去1級。這進一步導致我相信有一個問題「重新佈置」出來。

+0

你有Objective-C異常的斷點嗎?如果是這樣,如果在代碼被擊中後繼續執行,會發生什麼? Autolayout在違反約束條件時拋出異常,但在引發異常之前不會記錄實際錯誤。 – frozendevil 2013-03-26 00:52:04

+0

是的,但是它停止在打開或不打開斷點的同一點。繼續沒有做什麼,只是繼續在同一個地方。附上一個截圖,其中的內容與文中發佈的內容相同。 – 2013-03-26 16:51:18

+0

此外,我沒有看到正常的自動佈局調試消息有關不需要的限制等... – 2013-03-26 16:53:06

回答

4

基於卡爾·林德伯格的想法,我製備和使用下面的iOS類別和我沒有崩潰了:

的UIView + AddSubviewWithRemovingFromParent.h

#import <UIKit/UIKit.h> 

@interface UIView (AddSubviewWithRemovingFromParent) 

- (void)addSubviewWithRemovingFromParent:(UIView *)view; 

@end 

的UIView + AddSubviewWithRemovingFromParent。米

#import "UIView+AddSubviewWithRemovingFromParent.h" 

@implementation UIView (AddSubviewWithRemovingFromParent) 

- (void)addSubviewWithRemovingFromParent:(UIView *)view { 
    if (view.superview != nil) { 
     [view removeFromSuperview]; 
    } 
    [self addSubview:view]; 
} 

@end 

現在你可以使用addSubviewWithRemovingFromParent方法添加子視圖,而不是addSubview方法是這樣的:

UITableViewCell *cell = [[UITableViewCell alloc] init]; 
[cell.contentView addSubviewWithRemovingFromParent:<viewToAdd>]; 

概括起來:

  1. 找到addSubView的所有引用您的控制器應用程序 正在崩潰
  2. 導入類別UIView + AddSubviewWithRemovingF romParent.h
  3. 使用方法addSubviewWithRemovingFromParent代替addSubView
+0

您可以檢查視圖。 superview == self,如果是這種情況,只需調用[self bringSubviewToFront:view],而不是刪除然後重新添加。同樣的結果,應該更有效率。添加/刪除子視圖可能會觸發一些其他的東西,你可能會也可能不想要。 – 2013-11-06 19:54:26

+0

嗨,在我的情況下,有必要刪除並再次添加。問題是,UITableViewCell被實例化了多次,因爲'reloadDataTable'被調用了更多次。因此子視圖被添加到更多的一個視圖(它有兩個父母)。 iOS 7系統能夠從原始父級刪除視圖,而不是iOS 6。你現在可以說,好的,你不應該爲一個以上的家長添加一個視圖。是的,我同意,這是要走的路,但是系統應該具備這種能力(處理「多重父母」的情況),「我認爲」開箱即用「。 – ljboy 2013-11-07 06:02:01

+0

如果添加一個當前屬於另一個視圖層次結構的子視圖,那麼它應該被自動移出該視圖。也許在iOS6自動佈局中,那個部分沒有被清理乾淨。所以在你的情況下,是的,你需要在添加自己之前從當前的超級視圖中移除。但是,如果當前的超級觀點已經是你自己了,那麼就不需要刪除然後重新添加。這可能足以在您的代碼中檢查。但是,知道iOS7處理這個問題也是很好的(我懷疑它可能),所以上面的代碼可能只在iOS6上有必要。感謝那。 – 2013-11-07 07:25:49

7

我似乎還記得像這樣的東西,雖然不知道它是完全一樣的東西。在我的情況下,它是通過調用addSubview :(或insertSubview:...)與已經是子視圖的視圖引起的。雖然通常我認爲UIView會處理這個問題,但通過自動佈局,似乎有可能將某些相關信息添加到其他地方兩次,並且在嘗試清理相關信息時可能會發生崩潰。就我而言,解決方案是確保我只添加子視圖一次,而這次崩潰(或者類似的崩潰)消失了。

+0

真棒 - 這對我來說也是。快速調用[view removeFromSuperView]對其進行排序。謝謝@carl :-) – Matthew 2013-08-17 14:43:08

0

我有/有同樣的問題。
同樣的問題發生在我身上,當我將兩個視圖控制器模態地放在彼此之上並且想要返回到第一個時。 禁用自動佈局首次展示查看爲我解決了這個問題。
在你的情況self.presentingviewcontroller
不幸的是我無法進一步縮小範圍。

+0

無賴,聽起來像你沒有使用故事板?根據我的理解,如果您使用Storyboard,其中的每個場景/視圖都是自動佈局或不是....也許Xcode 5具有自動佈局增強功能,可以顯示/修復真正的問題 – 2013-07-30 18:10:33

1

對我來說,當我在故事板視圖控制器,但是從筆尖與同一視圖控制器的文件加載到瀏覽內容事故發生所有者。這通常可以正常工作,但我在故事板和NIB中都設置了出口,這觸發了iOS6「添加子視圖兩次」的錯誤。通過清理NIB中的視圖出口,所有的都是固定的。