8

I am experiencing a very strange crash, here is the backtrace.

* 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

You will notice frame 25 is the only call my code makes, and it is cancelButtonTouched which looks like.

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

I am at a loss as to what is going on, I've never had an issue like this before, based on the system calls it appears to be an auto-layout issue. I verified that viewWillApper is called on the presenting view controller before the crash occurs, so I assume it is an issuing during layout of the presenting view.

Any ideas on how to narrow this issue down to a specific layout contstraint? Or any other ideas?

This is reproduceable on some devices, where as on others it rarely if ever happens. So it is intermittent.

Update

Screenshot of breakpoint.

enter image description here

Update 2

So it is definitely an issue with dismissing to the presentingViewController, dismissing two levels deep ([self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil]) works fine, but obviously not the desired result, I only want to go back 1 level. This further leads me to believe there is an issue "re-laying" out the view.

Chris Wagner
  • 20,773
  • 8
  • 74
  • 95
  • Do you have a breakpoint on Objective-C exceptions? If so, what happens if you continue execution after this code is hit? Autolayout throws exceptions when it breaks constraints, but doesn't log the actual error until after the exception is thrown. –  Mar 26 '13 at 00:52
  • Yeah I do, but it stops at the same point with or without the breakpoint turned on. Continuing does nothing, just continues to hit the same spot. Attached a screenshot of where it is breaking, the stack is the same as posted in the text. – Chris Wagner Mar 26 '13 at 16:51
  • Also, I am not seeing the normal auto-layout debug messaging regarding unwanted constraints, etc... – Chris Wagner Mar 26 '13 at 16:53
  • I ended up disabling auto-layout and converting the entire project to springs and struts, it is working perfect now. I am at a loss and getting everything working with springs and struts took a few hours, but was A LOT easier than getting it to work in the first place with auto-layout. – Chris Wagner Mar 26 '13 at 22:33
  • Weird. My only other guess is that the problematic view controller had a weak reference to a view or constraint that got disposed of, and the auto layout system choked when trying to rebuild everything (looks like CFHash is probably throwing an exception on a NULL/nil). Auto layout does take some time to build familiarity with, but I generally think it's worth it. The WWDC videos help, and my friend gave a [fairly comprehensive talk on it](http://www.optshiftk.com/2013/01/auto-layout-slides-available/), but raw time commitment is needed, too. –  Mar 27 '13 at 02:58
  • That sounds pretty reasonable @frozendevil, I may go back to try and figure it out some day, or when we feel like we need the extra power that auto-layout provides. In reality our layout is pretty simple at this point so the stuff you get for "free" with auto-layout was minima l. I really want to utilize it to it's fullest potential once we move to a more advanced layout. Thanks for the ideas. – Chris Wagner Mar 27 '13 at 21:28
  • @ frozendevil i faced same issues. is there any solution ? Please reply. thanks in advance :) – Ashok Domadiya Oct 04 '13 at 13:25

4 Answers4

7

I seem to remember something like this, though not sure it was the exact same thing. In my case, it was caused by calling addSubview: (or insertSubview:...) with a view which already was a subview. While normally I think UIView deals with that, with auto layout it seems that it's possible for some associated information to be added elsewhere twice, and there can be a crash when trying to clean out that associated information. In my case, the solution was to ensure that I only added subviews once, and this crash (or my similar one anyways) went away.

Carl Lindberg
  • 2,902
  • 18
  • 22
  • Awesome - that was it for me too. A quick call to [view removeFromSuperView] sorted it. Thanks @carl :-) – Matthew Aug 17 '13 at 14:43
4

Based on idea of Carl Lindberg I prepared and used the following iOS category and I have no crash anymore:

UIView+AddSubviewWithRemovingFromParent.h

#import <UIKit/UIKit.h>

@interface UIView (AddSubviewWithRemovingFromParent)

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

@end

UIView+AddSubviewWithRemovingFromParent.m

#import "UIView+AddSubviewWithRemovingFromParent.h"

@implementation UIView (AddSubviewWithRemovingFromParent)

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

@end

now you can use the addSubviewWithRemovingFromParent method to add the subView instead of addSubview method like this:

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

To sum it up:

  1. find all references of addSubView in your controllers where the app is crashing
  2. import the category UIView+AddSubviewWithRemovingFromParent.h
  3. use method addSubviewWithRemovingFromParent instead of addSubView
ljboy
  • 219
  • 2
  • 8
  • You could probably check to see if view.superview == self, and if that is the case, just call [self bringSubviewToFront:view] rather than removing then re-adding. Same result and should be more efficient. Adding/removing subviews can trigger a bunch of other stuff, which you may or may not want. – Carl Lindberg Nov 06 '13 at 19:54
  • Hi, in my case it was necessary to remove and add again. The problem was, that the UITableViewCell was instantiated more times, because the `reloadDataTable` was called more times. Therefore the subview was added to more that one view (it had kind of two parents). The iOS 7 system was able to remove the view from the original parent, iOS 6 not. You can say now, ok, you should not add one view to more than one parent. Yes, I agree, it is way to go, but the system should have this ability (handling "multiple parent" situation) "out of the box" I think. – ljboy Nov 07 '13 at 06:02
  • If you add a subview which is currently part of another view hierarchy, then yes it should be automatically moved out of that view. Maybe in iOS6 auto layout, that part was not handled cleanly. So in your case, yes, you would need to remove from the current superview before adding to yourself. But if the current superview is already yourself, there should be no need to remove then re-add. That's probably common enough to check for in your code. But it's also good to know that iOS7 handles this (I suspected it might), so the above code may only be necessary on iOS6. Thanks for that. – Carl Lindberg Nov 07 '13 at 07:25
  • In my case the parent is UITableViewCell (its contentView) and the old one should not be presented, actually should be disposed or reused, so there is a place for improvement :) It could be also a memory leak in that case. – ljboy Nov 07 '13 at 08:53
1

In my case this crash happened when I had a view controller in a storyboard but loaded the view contents in from a NIB with the same view controller as the file owner. This normally works fine, but I had the view outlet set in both the storyboard and the NIB, which triggered the iOS6 "add subview twice" bug. By clearing the view outlet in the NIB all was fixed.

phatmann
  • 18,161
  • 7
  • 61
  • 51
0

I had / have the same problem.
The same problem occurs to me, when i present two view controllers modally above each other and want to return to the first one. Disabling autolayout for the first presented view only solves the issue for me.
In your case self.presentingviewcontroller
Unfortunately i wasn't able to narrow it down further.

Simon D.
  • 61
  • 1
  • 7
  • Bummer, sounds like you aren't using Storyboards? From what I understand if you use a Storyboard every scene/view within it is auto-layout or not.... Maybe Xcode 5 with auto-layout enhancements will reveal/fix the true problem – Chris Wagner Jul 30 '13 at 18:10