UIWebView subclass causing malloc_zone_unregister() in XCode 7 - ios

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?

Related

Crash on AutoLayout: Location anchors require being paired

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;
}

Crash in self.view after constructor on iOS 8.1 and 8.2

I'm trying to do a simple SpriteKit action - adding a view to a scene:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"LevelsEditorStoryboard" bundle:[NSBundle mainBundle]];
self.levelsEditor = [mainStoryboard instantiateViewControllerWithIdentifier:#"LevelsEditorId"];
[self.scene.view addSubview:self.levelsEditor.view];
On iOS 8.0 and 8.3 is working fine and on iOS 8.1 and 8.2 I'm getting the following error:
SPBingo[75304:80943666] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITextSelectionView name]: unrecognized selector sent to instance
I realised that this crash caused by the UITextField.
Once I'm getting rid of it, replacing the UITextField with some UITextView ( not ideal but whatever) The view is loading but when I try to click on a UITextView it crashed. The other Input views work (switches, dataPicker, tableView etc.)
After a deep dive into it I figured out that the problem occur in the contractor already. When I put breakpoint on the the second line in the following code :
-(instancetype) initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if(self)
{
}
return self;
}
and try to print "self.view" I'm getting the following error:
error: Execution was interrupted, reason: internal ObjC exception breakpoint(-3)..
The process has been returned to the state before expression evaluation.
ODD!
You cannot access the view until after the "viewDidLoad:" method signature is called, otherwise it attempts to create the view before all the prerequisites are in place.
Make sure to call self.view from "viewDidLoad:", "viewWillAppear:" or "viewDidAppear:" when it has properly been setup.
So.. it is an internal bug by Apple which create in 8.1 and fixed in 8.3.
The solution is avoid using the UITextView contractor "initWithFrame" and use the following one:
UITextView *textView = [[UITextView alloc] initWithFrame: frame textContainer: textContainer];

[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;
}
}

UIScrollView loses reference to delegate

I need to create a number of UIScrollViews dynamically and fill them with content. This is all good except when i set the delegate to self and pan the list i get this exception:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString scrollViewDidScroll:]: unrecognized selector sent to instance 0x7581230'
NSCFString obviously isn't my view controller (which implements the protocol UIScrollViewDelegate) so from what i gather somehow the memory gets messed up and it doesn't keep the reference correctly. Occasionally this can be something else too which strongly points to something being wrong with the memory
Here's the code to create the list:
for (NSUInteger i = 0; i < self.stories.currentStory.selectableWordCount; i++) {
UIScrollView *list = [[UIScrollView alloc] init];
list.alwaysBounceVertical = YES;
list.showsVerticalScrollIndicator = NO;
list.clipsToBounds = NO;
list.delegate = self;
list.pagingEnabled = YES;
[self.view addSubview:list];
.. // add UILabels to the list, set the frame, contentSize etc
[self.wordLists addObject:list]; // this is a #property (nonatomic, strong) NSMutableArray, declared in a private interface()
}
If i NSLog the delegate it's correct. respondsToSelector also matches fine. Interestingly if i comment out the scrollViewDidScroll: respondsToSelector: doesn't match any more and (probably because of this) the UIScrollView won't attempt to call this method any more. This then means that it can reach the delegate correctly to check for the method availability but when it gets called something goes wrong.
I'm targeting iOS5 with ARC. If this wasn't the case i would assume that i messed something up with the memory myself but now i don't have the same control.
I'm having a hard time debugging this issue, any help on how to proceed would be appreciated
D'uh. I was obviously looking in the wrong place. The view controller was added through a .xib and the view was pointing to a subview on the stage. However i needed to create an IBOutlet to the view controller in the main view controller to make sure it stays in memory. Hopefully this can help somebody else with a similar problem :)

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).

Resources