Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash when removing constraints on iOS 9 #331

Closed
3 tasks done
SlayterDev opened this issue Sep 22, 2016 · 15 comments
Closed
3 tasks done

Crash when removing constraints on iOS 9 #331

SlayterDev opened this issue Sep 22, 2016 · 15 comments

Comments

@SlayterDev
Copy link

New Issue Checklist

馃毇 If this template is not filled out your issue will be closed with no comment. 馃毇

  • I have looked at the Documentation
  • I have read the F.A.Q.
  • I have filled out this issue template.

Issue Info

Info Value
Platform iOS
Platform Version 9.3
SnapKit Version 0.22.0
Integration Method cocoapods

Issue Description

Since updating to Xcode 8, Swift 2.3, and SnapKit 0.22.0 we've been having an issue with removing constraints. We have a UIView that we need to change constraints for. Regardless if we are using:

view.snp_removeConstraints()
 view.snp_makeConstraints { (make) in
    ...
}

or:

view.snp_remakeConstraints { (make) in
    ...
}

It always crashes when trying to remove the constraints. The crash happens in Constraint.swift in uninstallFromView(). The crash occurs in the following block of code:

// remove the constraints from the UIView's storage
#if SNAPKIT_DEPLOYMENT_LEGACY && !os(OSX)
if #available(iOS 8.0, *) {
    NSLayoutConstraint.deactivateConstraints(installedLayoutConstraints)
} else if let installedOnView = installInfo.view {
    installedOnView.removeConstraints(installedLayoutConstraints)
}
#else
    NSLayoutConstraint.deactivateConstraints(installedLayoutConstraints) // < -- *** This line ***
#endif

Is this an issue in the iOS SDK or perhaps an issue in SnapKit? Any help would be appreciated.

@robertjpayne
Copy link
Member

@SlayterDev can you please post the stack trace and/or exception info?

@SlayterDev
Copy link
Author

SlayterDev commented Sep 23, 2016

Stack trace:

* thread #1: tid = 0x53efd6, 0x000000010a5e180b libobjc.A.dylib`objc_msgSend + 11, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
    frame #0: 0x000000010a5e180b libobjc.A.dylib`objc_msgSend + 11
    frame #1: 0x000000010a347b9f Foundation`+[NSLayoutConstraint _addOrRemoveConstraints:activate:] + 216
  * frame #2: 0x000000010806d18d SnapKit`ConcreteConstraint.uninstallFromView(self=0x00007feaf2300ab0) -> () + 621 at Constraint.swift:373
    frame #3: 0x0000000108064e85 SnapKit`ConcreteConstraint.uninstall(self=0x00007feaf2300ab0) -> () + 21 at Constraint.swift:139
    frame #4: 0x000000010807b322 SnapKit`static ConstraintMaker.removeConstraints(view=0x00007feaebcc4b20, self=SnapKit.ConstraintMaker) -> () + 658 at ConstraintMaker.swift:193
    frame #5: 0x0000000108079f00 SnapKit`static ConstraintMaker.remakeConstraints(view=0x00007feaebcc4b20, file="/Users/user/Code/marketplace-ios/DuctTape/AccountViewController.swift", line=516, closure=0x0000000105844c70 CARE`partial apply forwarder for CARE.AccountViewController.(tableView (__ObjC.UITableView, viewForHeaderInSection : Swift.Int) -> Swift.Optional<__ObjC.UIView>).(closure #1) at AccountViewController.swift, self=SnapKit.ConstraintMaker) -> ()) -> () + 368 at ConstraintMaker.swift:169
    frame #6: 0x00000001080803ad SnapKit`UIView.snp_remakeConstraints(file="/Users/user/Code/marketplace-ios/DuctTape/AccountViewController.swift", line=516, closure=0x0000000105844c70 CARE`partial apply forwarder for CARE.AccountViewController.(tableView (__ObjC.UITableView, viewForHeaderInSection : Swift.Int) -> Swift.Optional<__ObjC.UIView>).(closure #1) at AccountViewController.swift, self=0x00007feaebcc4b20) -> ()) -> () + 173 at View+SnapKit.swift:160
    frame #7: 0x0000000105841f2e CARE`AccountViewController.tableView(tableView=0x00007feaec835c00, section=0, self=0x00007feaeda78800) -> UIView? + 1182 at AccountViewController.swift:531
    frame #8: 0x0000000105844d12 CARE`@objc AccountViewController.tableView(UITableView, viewForHeaderInSection : Int) -> UIView? + 66 at AccountViewController.swift:0
    frame #9: 0x00000001084a7e78 UIKit`-[UITableView _delegateViewForHeaderInSection:] + 59
    frame #10: 0x00000001084abfb7 UIKit`__96-[UITableView _sectionHeaderView:withFrame:forSection:floating:reuseViewIfPossible:willDisplay:]_block_invoke + 73
    frame #11: 0x00000001083ff680 UIKit`+[UIView(Animation) performWithoutAnimation:] + 65
    frame #12: 0x00000001084abe1a UIKit`-[UITableView _sectionHeaderView:withFrame:forSection:floating:reuseViewIfPossible:willDisplay:] + 674
    frame #13: 0x00000001084ac94d UIKit`-[UITableView _sectionHeaderViewWithFrame:forSection:floating:reuseViewIfPossible:willDisplay:] + 85
    frame #14: 0x0000000108480b52 UIKit`-[UITableView _updateVisibleHeadersAndFootersNow:] + 3102
    frame #15: 0x00000001084821d4 UIKit`-[UITableView _updateVisibleCellsNow:isRecursive:] + 4153
    frame #16: 0x00000001084b6686 UIKit`-[UITableView _performWithCachedTraitCollection:] + 92
    frame #17: 0x000000010849d344 UIKit`-[UITableView layoutSubviews] + 224
    frame #18: 0x000000010840a980 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 703
    frame #19: 0x0000000107e72c00 QuartzCore`-[CALayer layoutSublayers] + 146
    frame #20: 0x0000000107e6708e QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 366
    frame #21: 0x0000000107e66f0c QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 24
    frame #22: 0x0000000107e5b3c9 QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 277
    frame #23: 0x0000000107e89086 QuartzCore`CA::Transaction::commit() + 486
    frame #24: 0x0000000107e897f8 QuartzCore`CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 92
    frame #25: 0x000000010aa7cc37 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    frame #26: 0x000000010aa7cba7 CoreFoundation`__CFRunLoopDoObservers + 391
    frame #27: 0x000000010aa727fb CoreFoundation`__CFRunLoopRun + 1147
    frame #28: 0x000000010aa720f8 CoreFoundation`CFRunLoopRunSpecific + 488
    frame #29: 0x000000010f13cad2 GraphicsServices`GSEventRunModal + 161
    frame #30: 0x000000010834ff09 UIKit`UIApplicationMain + 171
    frame #31: 0x00000001055c27f2 CARE`main + 114 at AppDelegate.swift:21
    frame #32: 0x000000010b8a192d libdyld.dylib`start + 1

Exception:
Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

@robertjpayne
Copy link
Member

@SlayterDev does this crash happen everytime? EXEC_BAD_ACCESS is a memory violation but it looks like it's coming from inside UIKit.

It could in theory be dealloc'd constraints getting passed into that function call.

Just to be 100% sure your constraint code is always running on the main thread right?

@SlayterDev
Copy link
Author

I would agree that it seems to be dealloc'd constraints being passed. But I'm not sure how they are being dealloc'd between that time. We have a few other places where we call remake but it still seems to work. My current fix is to rebuild the view from scratch and reassign necessary properties. It's still weird this only happens on iOS 9.

@robertjpayne
Copy link
Member

@SlayterDev it seems fishy, no other reports of this yet. Is it something you can extract to a small sample project?

@robertjpayne
Copy link
Member

Closing due to inactivity and inability to reproduce.

@skywalkerlw
Copy link

skywalkerlw commented Dec 7, 2016

I have a very similar case here. (Xcode8.1 on iPhone6plus with iOS10)

The error msg is (no detailed error message):
"libc++abi.dylib: terminating with uncaught exception of type NSException", which happened when rotating device. The tracetree is shown as below

image

update: this crash happened more frequently if the method of remakeConstraints is called frequently like 10 times per seconds

@robertjpayne
Copy link
Member

@wangbourne whats the actual exception info? ObjC messages normally contain lots of good info about what went wrong if you let them crash your app rather than breaking on them.

@skywalkerlw
Copy link

Actually that's the only message i can see from Xcode (i didn't break on them :) )

@robertjpayne
Copy link
Member

@wangbourne objective-c exceptions should output stuff into a crash log or the console if they are uncaught and crash your app.

From looks of this you have a breakpoint setup on "All Objective-C Exceptions" this breakpoint breaks even for exceptions that are caught, if you continue and you don't see any additional error messaging or a crash it's probably an exception that isn't important ( iOS is internally suppressing it )

@skywalkerlw
Copy link

skywalkerlw commented Dec 7, 2016

i got above error message without any breakpoint, then i tried to find out the root cause, so i set breakpoint at exceptions, and got above screenshot.
so i'm quite sure, that error message is all I could get :)

@robertjpayne
Copy link
Member

@wangbourne ah so you're getting an EXEC_BAD_ACCESS after it breaks? Any chance you have a small project that reproduces it easily?

@xiaohongjun0509
Copy link

@robertjpayne hi robertjpayne, in our project I鈥榲e meet this crash. Also this crash only occur on iOS9.
this occurs due to removeConstraints has passed a dealloc obj.

---<UIView: 0x7fcc51cd29d0; frame = (-1 -1; 377 377); layer = <CALayer: 0x7fcc51dec2a0>>
---[<NSAutoresizingMaskLayoutConstraint:0x7fcc5440c610 NewsMaster.GIFPlayer:0x7fcc54395e80.(null) == UIView:0x7fcc51cd29d0.(null)>, <NSAutoresizingMaskLayoutConstraint:0x7fcc54471170 NewsMaster.GIFPlayer:0x7fcc54395e80.width == UIView:0x7fcc51cd29d0.width>, <NSAutoresizingMaskLayoutConstraint:0x7fcc540f0430 NewsMaster.GIFPlayer:0x7fcc54395e80.(null) == UIView:0x7fcc51cd29d0.(null)>, <NSAutoresizingMaskLayoutConstraint:0x7fcc544e8fc0 NewsMaster.GIFPlayer:0x7fcc54395e80.height == UIView:0x7fcc51cd29d0.height>]
---bgImageView------><Hermes.NewsImageView: 0x7fcc5480c570; baseClass = UIImageView; frame = (0 0; 0 0); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7fcc5480cba0>>
---<UIView: 0x7fcc51cd29d0; frame = (-1 -1; 377 377); layer = <CALayer: 0x7fcc51dec2a0>>
---[<NSAutoresizingMaskLayoutConstraint:0x7fcc5440c610 NewsMaster.GIFPlayer:0x7fcc54395e80.(null) == UIView:0x7fcc51cd29d0.(null)>, <NSAutoresizingMaskLayoutConstraint:0x7fcc54471170 NewsMaster.GIFPlayer:0x7fcc54395e80.width == UIView:0x7fcc51cd29d0.width>, <NSAutoresizingMaskLayoutConstraint:0x7fcc540f0430 NewsMaster.GIFPlayer:0x7fcc54395e80.(null) == UIView:0x7fcc51cd29d0.(null)>, <NSAutoresizingMaskLayoutConstraint:0x7fcc544e8fc0 NewsMaster.GIFPlayer:0x7fcc54395e80.height == UIView:0x7fcc51cd29d0.height>]
---bgImageView------><Hermes.NewsImageView: 0x7fcc5480c570; baseClass = UIImageView; frame = (0 0; 0 0); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7fcc5480cba0>>
NewsImageView dealloc ---> <Hermes.NewsImageView: 0x7fcc54689470; baseClass = UIImageView; frame = (0 0; 0 0); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7fcc54689960>>
NewsImageView dealloc ---> <Hermes.NewsImageView: 0x7fcc5480c570; baseClass = UIImageView; frame = (0 18; 375 375); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7fcc5480cba0>>

---<UIView: 0x7fcc51cd29d0; frame = (-1 -1; 377 377); layer = <CALayer: 0x7fcc51dec2a0>>
---[<NSAutoresizingMaskLayoutConstraint:0x7fcc5418b870 NewsMaster.GIFPlayer:0x7fcc54395e80.(null) == UIView:0x7fcc51cd29d0.(null)>, <NSAutoresizingMaskLayoutConstraint:0x7fcc545751e0 NewsMaster.GIFPlayer:0x7fcc54395e80.width == UIView:0x7fcc51cd29d0.width>, <NSAutoresizingMaskLayoutConstraint:0x7fcc545884a0 NewsMaster.GIFPlayer:0x7fcc54395e80.(null) == UIView:0x7fcc51cd29d0.(null)>, <NSAutoresizingMaskLayoutConstraint:0x7fcc545e3a00 NewsMaster.GIFPlayer:0x7fcc54395e80.height == UIView:0x7fcc51cd29d0.height>]

2017-12-05 16:34:27.082 [41765:977382] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[WKWebsiteDataStore nsli_layoutEngine]: unrecognized selector sent to instance 0x7fcc5480c570'
*** First throw call stack:

@alexvbush
Copy link

Experiencing the same issue.

It happens in Constraint#deactivateIfNeeded method when trying to access let layoutConstraints = self.layoutConstraints on iOS 9. Breaks with bad_acess error as described by other comments above.

internal func deactivateIfNeeded() {
        guard let item = self.from.layoutConstraintItem else {
            print("WARNING: SnapKit failed to get from item from constraint. Deactivate will be a no-op.")
            return
        }
        let layoutConstraints = self.layoutConstraints
        NSLayoutConstraint.deactivate(layoutConstraints)
        item.remove(constraints: [self])
    }

@Liaoworking
Copy link

I had encounter the same crash. finally, I find that some of view's contrains is 0x0000000, it's nil. I change the time to use snp_removeConstraints() function. It worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants