Crash on AutoLayout: Location anchors require being paired - ios

The app is crashing on Location anchors require being paired.. I would like to fix it, however no matter how many times did I manually tested the app with this view, I've never run into the crash (got only logs on Crashlytics). Anyone knows what may be wrong here, under what circumstances the crash may happen?
The property centerYConstraint is required because later it allows the user to move the view up/down.
Part of MyView.m file. The crash happens on setting self.centerYConstraint.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.centerYConstraint = [self.view.centerYAnchor constraintEqualToAnchor:self.parentViewController.view.centerYAnchor
constant:self.view.center.y - self.parentViewController.view.center.y];
self.centerYConstraint.active = YES;
}
Crash log:
Fatal Exception: NSInvalidArgumentException
NSLayoutConstraint for <NSLayoutYAxisAnchor:0x16764ae0 "MyView:0x18e6b900.centerY">:
A constraint cannot be made from <NSLayoutYAxisAnchor:0x16764ae0 "MyView:0x18e6b900.centerY"> to a constant.
Location anchors require being paired.

This exception happens when constraintEqualToAnchor:self.parentViewController.view.centerYAnchor gives nil, which might be when self.parentViewController.view is nil, or self.parentViewController is nil.
All hierarchy logic is not clear from description, but the following does solve the issue (assuming that superview is a view of parent controller, otherwise just some more conditions should be added).
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.centerYConstraint = [self.view.centerYAnchor constraintEqualToAnchor:self.superview.centerYAnchor
constant:self.view.center.y - self.superview.center.y];
self.centerYConstraint.active = YES;
}

Related

UIWebView subclass causing malloc_zone_unregister() in XCode 7

I'm running my project in XCode 7 and I'm trying to hunt down some EXC_BAD_ACCESS KERN_INVALID_ADDRESS which my users on the AppStore are experiencing.
I'm running XCode 7 with Enable Address Sanitizer on. After the app starts and all the init is done I see these warnings int the console:
IKMS(1001,0x60081000) malloc: *** malloc_zone_unregister() failed for 0x1a8ad000
==1001==__asan_mz_destroy() called -- ignoring
IKMS(1001,0x60081000) malloc: *** malloc_zone_unregister() failed for 0x1a8b0000
==1001==__asan_mz_destroy() called -- ignoring
IKMS(1001,0x60081000) malloc: *** malloc_zone_unregister() failed for 0x1a8ab000
==1001==__asan_mz_destroy() called -- ignoring
After some debugging I found that this happens when during my initial allocation in the AppDelegate of the app, if I create a CustomWebview and set it's frame when the app becomes active this error appears.
This is the init function of the custom UIWebView:
- (id) init
{
if (self = [super init])
{
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
self.scalesPageToFit = YES;
self.userInteractionEnabled = NO;
self.delegate = self;
}
return self;
}
This is how I initialise it:
CustomUIWebView *custom = [[CustomUIWebView alloc] init];
custom.frame = CGRectMake(109/2, 220/2, 326/2, 326/2);
[anotherView addSubview:custom];
If I move this line:
custom.frame = CGRectMake(109/2, 220/2, 326/2, 326/2);
After the app becomes active the errors go away.
This of course is part of a bigger project and I fixed all errors like this but I still get these errors in the console. So basically I have these questions:
Are there any other views that behave like this?
Do you know by any chance why this error occurs? EXC_BAD_ACCESS
KERN_INVALID_ADDRESS Maybe besides memory overwrite and out of
memory?
Is there way to catch these errors when they happen rather than when
they crash the app? (The memory ones).
Do you know by any chance why this error occurs? EXC_BAD_ACCESS KERN_INVALID_ADDRESS Maybe besides memory overwrite and out of memory?
You should execute the designated initializer, when you step up from a subclass' initializer. The designated initializer for UIView and its subclass UIWebView is -initWithFrame:, not -init. To do so, you have to pass a frame rest to your initializer or to set a default one. So it should be (option 1):
- (id) initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
…
}
return self;
}
…
CustomUIWebView *custom = [[CustomUIWebView alloc] initWithFrame:CGRectMake(109/2, 220/2, 326/2, 326/2)];
BTW: Do you know, that 109/2 is an integer division with the result 54, not 54.5?
Are there any other views that behave like this?
I do not know, whether views behaves exactly like this. But almost every view will need to know the frame at initialization.
Is there way to catch these errors when they happen rather than when they crash the app? (The memory ones).
I'm not sure, what you want to say. Maybe exception breakpoint?

[CustomViewController respondsToSelector:]: message sent to deallocated instance

This is used to work fine for my pre-ARC code, but since refactoring all the project to be ARC compatible, I start getting this crash:
[CustomViewController respondsToSelector:]: message sent to deallocated instance
My project is an iPad app with a split view, but contrary to apple documentation, previous developer has put another view controller to be visible on app launch before split view. So I know this is not the right way to do, but as I said it used to work before ARC integration so I need to get a workaround with this.
The root view controller which contain a menu of items, each item display a detail form to be filled, then a click on next button move to the next detail screen, etc.
The issue starts when I click on home button put on root view to get back to the home view, here is the relevant code that move the user to the home screen:
//this method is in the appdelegate, and it gets called when clikc on home button located on the root view
- (void) showHome
{
homeController.delegate = self;
self.window.rootViewController = homeController;
[self.window makeKeyAndVisible];
}
Then when I click on a button to get back to the split view (where are the root/details view), the app crashes with the above description. I profiled the app with instruments and the line of code responsible of that is located in the RootViewController, in the didSelectRowAtIndexPath method, here is the relevant code:
if(indexPath.row == MenuCustomViewController){
self.customVC=[[CustomViewController alloc] initWithNibName:#"CustomVC"
bundle:nil];
[viewControllerArray addObject:self.customVC];
self.appDelegate.splitViewController.delegate = self.customVC;
}
customVC is a strong property, I tried to allocate directly and assign to the instance variable but that didn't help to fix the crash. Any thoughts ?
EDIT:
Here is the stack trace given by instruments:
[self.appDelegate.splitViewController setViewControllers:viewControllerArray];//this line caused the crash
[viewControllerArray addObject:self.appDescVC];//this statement is called before the above one
self.custinfoVC=[[CustInfoViewController alloc] initWithNibName:#"CustInfo" bundle:nil];//this statement is called before the above one
self.appDelegate.splitViewController.delegate = self.appDescVC;//this statement is called before the above one
custinfoVC and appDescVC are strong properties.
I solved this problem by setting my delegates and datasources to nil in the dealloc method. Not sure if it'll help you but its worth a try.
- (void)dealloc
{
homeController.delegate = nil;
//if you have any table views these would also need to be set to nil
self.tableView.delegate = nil;
self.tableView.dataSource = nil;
}
You may want to setup the CustomViewController during app launch, and display the other views modally on top if necessary. The error message you're getting is because something is getting released by ARC prematurely. It might have not manifested before because pre-arc stuff wasn't always deallocated immediately. ARC is pretty serious about releasing stuff when it leaves scope
Hard to tell without seeing a lot more of the code involved, and what line it breaks on, etc.
This:
- (void) showHome {
//THIS: where is homeController allocated?
homeController.delegate = self;
self.window.rootViewController = homeController;
[self.window makeKeyAndVisible];
}
EDIT:
Add this line right above the line that causes your crash
for (id object in viewControllerArray) {
NSLog(#"Object: %#",object);
}
I had the same Problem.If you are not using "dealloc" method then use "viewWillDisappear" to set nil.
It was difficult to find which delegate cause issue, because it does not indicate any line or code statement for my App So I have try some way to identify delegate, Maybe it becomes helpful to you.
1.Open xib file and from file's owner, Select "show the connections inspector" right hand side menu. Delegates are listed, set them to nil which are suspected.
(Same as my case)Property Object like Textfield can create issue, So set its delegate to nil.
-(void) viewWillDisappear:(BOOL) animated{
[super viewWillDisappear:animated];
if ([self isMovingFromParentViewController]){
self.countryTextField.delegate = nil;
self.stateTextField.delegate = nil;
}
}

How can I keep my UIGestureRecognizers from crashing?

I'm having a really frustrating issue with UIGestureRecognizers. They get added fine, but whenever one gets triggered, it crashes with the message EXC_BAD_ACCESS (code=1, address=0xf0000008). I'm adding it in the view controller using the following code:
- (void)handleDrag:(UIGestureRecognizer *)sender {
NSLog(#"%#", sender);
}
- (void)viewDidLoad {
[super viewDidLoad];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handleDrag:)];
[self.windowBar addGestureRecognizer:panGesture];
}
self.windowBar is a UIImageView. I've enabled user interaction on said UIImageView. But whenever I start actually dragging it, it crashes.
I'm not sure if this has anything to do with it, but I'm using the new ARC feature.
What else am I missing? :(
Try running with the Zombies Instrument to detect exactly which zombie (already released) object is being referenced. It will point you to the exact object that the system thinks it should send a message to, but has already been released (with retain count set to 0, and the memory already reassigned).

iOS - removeFromSuperview crashes the app sometimes

I have a page with a back button that takes me to an inbox. I do this in viewWillDisappear -
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[inboxToolbar removeFromSuperview ];
[inboxToolbar release];
}
If I do this a few times, the app crashes and the exception thrown is "unrecognized selector sent to instance". This happens very intermittently. Any thoughts on how to go about fixing / debugging it?
Assuming the crash is accessing your inboxToolbar ivar, change your code to the following:
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[inboxToolbar removeFromSuperview ];
[inboxToolbar release];
inboxToolbar = nil;
}
This will ensure inboxToolbar does not keep a pointer to a deallocated object. You could also have other issues, would need to see the crash log and more of your code to be sure.
add an exception break point to see where it is being thrown, you probably are sending a message to an object that isn't of the class that you believe it to be, after you have stopped on the exception breakpoint, you can hover over the variable to see what classes they belong to.
if that doesn't help post the actual message and perhaps we can help more, could be iOS version issue, etc.
Try checking whether it will respond to your method first...
if ([inboxToolbar respondsToSelector:#selector(removeFromSuperview)]) {
[inboxToolbar removeFromSuperview];
}

How to recover from viewDidUnload(after memory warnings), using UISplitViewController

I'm making a split-view based iPad application(Portrait mode only), and I want to know how to recover initial state after viewDidUnload is called.
When split-view application started for the first time,
-splitViewController:willHideViewController:withBarButtonItem:forPopoverController:
is called automatically (right after -viewDidLoad).
I prepares UIBarButtonItems in the method.
If I open modal dialog or something with UIWebViewController (it consumes a lot of memory), application receives memory warning, viewDidUnload(s) are called.
When I close the modal dialog, -viewDidLoad is called automatically, but this time
-splitViewController:willHideViewController:withBarButtonItem:forPopoverController: is not called.
I prepares UIBarButtonItems in
-splitViewController:willHideViewController:withBarButtonItem:forPopoverController:
but it is not called, so buttons are dismissed.
In that case, should I call the method manually?
I found similar posting here.
https://github.com/grgcombs/IntelligentSplitViewController/issues/6
Thanks.
I don't know it is OK to answer to my own question, but maybe I found an answer for this. http://osdir.com/ml/cocoa-dev/2011-02/msg00430.html
It says that we should preserve BarButtonItems in viewDidUnload, and load it in viewDidLoad.
It seems working fine.
- (void)viewDidUnload {
[super viewDidUnload];
self.toolbarItems = self.toolbar.items; // property with retain policy
}
- (void)viewDidLoad {
[super viewDidLoad];
if (self.toolbarItems) {
self.toolbar.items = self.toolbarItems;
self.toolbarItems = nil;
}
}

Resources