removeFromSuperview EXC_BAD_ACCESS - ios

I've developed a game for iPhone starting from iOS 6.0.
It works fine on my 5S running on iOS 7.1 but when testing it on my old 3GS with iOS 6.1.3, it crash with a "EXC_BAD_ACCESS code:0" when trying to remove some custom UIView from superview.
I logged my custom view and it's superview (that are not nil), but nothing to do it work !
Also tried logging my views and superviews with lldb command and it confirms they are not nil.
Any idea ?? Can't understand how it could work on iOS7 and not on iOS6 !
Here the code when I get the error :
- (void)didMoveToParentViewController:(UIViewController *)parent{
if(parent == nil){
for (LevelNumberView *button in self.levelButtons) {
if(self.view && [self.view.subviews containsObject:button]){
NSLog(#"-- button:%#", button);
[button removeFromSuperview];
}
}
self.levelButtons = nil;
[self.titleView removeFromSuperview];
self.titleView = nil;
[self.view removeFromSuperview];
self.delegate = nil;
}
}

You should be able to call removeFromSuperview on any valid UIView (whether it has a superview or not) so that should not cause an error. My guess would be one of the pointers (that is not nil) is pointing to a released object.

I fix the same issue using check the superview before remove it :
if(self.loadingView.superview){
[self.loadingView removeFromSuperview];
}

Related

"NSInternalInconsistencyException [...] Sigh. Contentview size is zero." crash when using a UINavigationController

My code runs perfectly fine on iOS 10.3.3, whereas when I run the same code on iOS 11.2.1, it causes a crash at launch time with the following error:
Assertion failure in -[_UINavigationBarVisualProviderModernIOS _contentViewFittingHeight], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3698.33.7/_UINavigationBarVisualProviderModernIOS.m:569
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Sigh. Contentview size is zero.'
I cleaned the code, cleared the derived data, but those did not solve the issue.
There was an issue in the library I was using for Slide menu "iOS-Slide-Menu". So, I simply changed this two very methods in the library which then worked fine.
- (void)setup
{
[[NSUserDefaults standardUserDefaults] setObject:nil forKey:#"ssidName"];
[[NSUserDefaults standardUserDefaults] synchronize];
if (singletonInstance)
NSLog(#"Singleton instance already exists. You can only instantiate one instance of SlideNavigationController. This could cause major issues");
singletonInstance = self;
self.menuRevealAnimationDuration = MENU_SLIDE_ANIMATION_DURATION;
self.menuRevealAnimationOption = MENU_SLIDE_ANIMATION_OPTION;
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
// Update shadow size of enabled
if (self.enableShadow)
self.view.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.bounds].CGPath;
self.landscapeSlideOffset = self.view.frame.size.width/6;
self.portraitSlideOffset = self.view.frame.size.width/6;
self.panGestureSideOffset = 0;
self.avoidSwitchingToSameClassViewController = YES;
self.enableShadow = YES;
self.enableSwipeGesture = NO;
self.delegate = self;
// When menu open we disable user interaction
// When rotates we want to make sure that userInteraction is enabled again
[self enableTapGestureToCloseMenu:NO];
if (self.menuNeedsLayout)
{
[self updateMenuFrameAndTransformAccordingToOrientation];
// Handle different horizontal/vertical slideOffset during rotation
// On iOS below 8 we just close the menu, iOS8 handles rotation better so we support keepiong the menu open
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0") && [self isMenuOpen])
{
Menu menu = (self.horizontalLocation > 0) ? MenuLeft : MenuRight;
[self openMenu:menu withDuration:0 andCompletion:nil];
}
self.menuNeedsLayout = NO;
}
}
Fixed out, that two lines must be in viewWillLayoutSubviews instead of setup method. And like #Ishika said, this is the problem of iOS-Slide-Menu.
self.enableShadow = YES;
self.enableSwipeGesture = YES;
This error occured to me with Xcode 10.2.1 and SideMenu 6.0.4. I ended up configuring the navigation controller programmatically, which solved the issue.
let sideMenuVc = UISideMenuNavigationController(rootViewController: <view controller>)

SlideMenu not detecting touches for dismiss menu on iOS 11. Why?

I'm using the pod iOS-Slide-Menu repo in one of my personal projects.
If I run my project on iOS < 11 everything works as expected: When the side menu (blue view controller), touching outside it, i.e. the green part. Automatically closes it
But running on a device with iOS 11 the menu does't get closed when tapping outside.
Another curious situation is that this only happen with recently compiled versions (currently using Xcode 9.0), running the App Store version on a iOS11 device also works correctly.
So my questions are:
Why is this happening?
How can I avoid this to happen without replacing the whole library?
I created a SAMPLE PROJECT in github to reproduce the problem.
In your SlideNavigationController.m file go to viewWillLayoutSubviews method and remove or comment below line
[self enableTapGestureToCloseMenu:NO];
It is because viewWillLayoutSubviews method gets called in ios 11 initially!
so, from viewWillLayoutSubviews, enableTapGestureToCloseMenu gets called and it is removing gesture recognizer from right menu!
Hello #Adrime i have downloaded your code and tested in Xcode 9.0
found same issue like you have. outside tapped not closed view.
after seeing library i have found one solution.
In SlideNavigationController.m file,
one method is already created which is - (void)enableTapGestureToCloseMenu:(BOOL)enable
in that method, just comment this one line [self.view removeGestureRecognizer:self.tapRecognizer];
and your problem is solved.
this line removedGesture of tapping outside.
Updated:
I got it what you want, just change your viewWillLayoutSubviews method
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
// Update shadow size of enabled
if (self.enableShadow)
self.view.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.bounds].CGPath;
// When menu open we disable user interaction
// When rotates we want to make sure that userInteraction is enabled again
//[self enableTapGestureToCloseMenu:NO];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0"))
self.interactivePopGestureRecognizer.enabled = YES;
self.topViewController.view.userInteractionEnabled = YES;
if (self.menuNeedsLayout)
{
[self updateMenuFrameAndTransformAccordingToOrientation];
// Handle different horizontal/vertical slideOffset during rotation
// On iOS below 8 we just close the menu, iOS8 handles rotation better so we support keepiong the menu open
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0") && [self isMenuOpen])
{
Menu menu = (self.horizontalLocation > 0) ? MenuLeft : MenuRight;
[self openMenu:menu withDuration:0 andCompletion:nil];
}
self.menuNeedsLayout = NO;
}
}
What I Did : Do comment //[self enableTapGestureToCloseMenu:NO]; code and put below code
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0"))
self.interactivePopGestureRecognizer.enabled = YES;
self.topViewController.view.userInteractionEnabled = YES;
OLD:
It's Because in SlideNavigationController.m file you are calling [self enableTapGestureToCloseMenu:NO];
Just remove it or make condition for iOS 11 to pass YES for all
For EX.
if (IOS_VERSION == 11) {
[self enableTapGestureToCloseMenu:YES];
}
else {
[self enableTapGestureToCloseMenu:NO];
}
Because when you open your slide menu or click on green area alway call
[self enableTapGestureToCloseMenu:NO];
So as per method code
- (void)enableTapGestureToCloseMenu:(BOOL)enable
{
if (enable)
{
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0"))
self.interactivePopGestureRecognizer.enabled = NO;
self.topViewController.view.userInteractionEnabled = NO;
[self.view addGestureRecognizer:self.tapRecognizer];
}
else
{
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0"))
self.interactivePopGestureRecognizer.enabled = YES;
self.topViewController.view.userInteractionEnabled = YES;
[self.view removeGestureRecognizer:self.tapRecognizer];
}
}
It's removeGestureRecognizer for view.

React Native RCTCustomScrollView broken after upgrading to Xcode8

Apparently, this is a well known issue for react native when upgrading to Xcode 8. I have followed this guide to fix the error I am having, but I still get the following error when my app tries to load a <ScrollView/> component.
[RCTCustomScrollView refreshControl]: unrecognized selector sent to instance 0x16099e00
The code in my RCTScrollView.m that everybody seems to think causes the problem is shown below:
- (void)setRefreshControl:(RCTRefreshControl *)refreshControl
{
if (refreshControl) {
[refreshControl removeFromSuperview];
}
refreshControl = refreshControl;
[self addSubview:refreshControl];
}
- (void)removeReactSubview:(UIView *)subview
{
if ([subview isKindOfClass:[RCTRefreshControl class]]) {
_scrollView.refreshControl = nil;
} else {
RCTAssert(_contentView == subview, #"Attempted to remove non-existent subview");
_contentView = nil;
[subview removeFromSuperview];
}
}
Everything seems to work fine when I run this on a device running iOS 10.1.1, but when I try on a device running 9.3, it crashes when it tries to load a <ScrollView/>.
Important Note
- I am running react native 0.28 and am in a tight situation where I can't upgrade right now, thus I have to make the fixes manually.
I know this is an older post, but for Xcode 8, iOS 9.3 (iPad 2/iPad Mini), React Native 0.24.1, I made this change in RCTScrollView.m as a fix.
#implementation RCTCustomScrollView
{
__weak UIView *_dockedHeaderView;
// Added the following line
RCTRefreshControl *_refreshControl;
}
// Also added this
#synthesize refreshControl = _refreshControl;
The only solution I found is this, go to RCTScrollView.m and replace [_scrollView refreshControl] with [_scrollView respondsToSelector: #selector(refreshControl)]
- (NSArray<UIView *> *)reactSubviews
{
if (_contentView && [_scrollView respondsToSelector: #selector(refreshControl)]) {
return #[_contentView, [_scrollView refreshControl]];
}
return _contentView ? #[_contentView] : #[];
}

recursive swizzling causes crash

I'm using DAKeyboardControll on my app .
it has a method with name : swizzled_addSubview and implement Like this:
- (void)swizzled_addSubview:(UIView *)subview
{
if (!subview.inputAccessoryView)
{
if ([subview isKindOfClass:[UITextField class]])
{
UITextField *textField = (UITextField *)subview;
if ([textField respondsToSelector:#selector(setInputAccessoryView:)])
{
UIView *nullView = [[UIView alloc] initWithFrame:CGRectZero];
nullView.backgroundColor = [UIColor clearColor];
textField.inputAccessoryView = nullView;
}
}
else if ([subview isKindOfClass:[UITextView class]]) {
UITextView *textView = (UITextView *)subview;
if ([textView respondsToSelector:#selector(setInputAccessoryView:)] && [textView respondsToSelector:#selector(isEditable)] && textView.isEditable)
{
UIView *nullView = [[UIView alloc] initWithFrame:CGRectZero];
nullView.backgroundColor = [UIColor clearColor];
textView.inputAccessoryView = nullView;
}
}
}
[self swizzled_addSubview:subview];
}
problem
recently in my new version that compatible with AutoLayout , i receive some crash on this method , and reasons of them :
-[UIView(DAKeyboardControl) swizzled_addSubview:] ,
EXC_BAD_ACCESS KERN_PROTECTION_FAILURE at 0x0090dffc
i know this problem has happened for many many call , but why it can't work correctly ?
this crash happened only for 8 users for 54 times , 50 % of them has a jailbreak Device , but another person has a non- jailbreak Device !
Method swizzling causes issues at run time. I also got same kind of exception, To get rid of this, I have used BABFrameObservingInputAccessoryView, which is working fine for me. https://github.com/brynbodayle/BABFrameObservingInputAccessoryView
Most likely your method isn't actually swizzled, so you get a recursive call which will obviously crash. That's the tricky thing about swizzling: It exchanges two methods, so every call to addSubview would call swizzled_addSubview and the call to swizzled_addSubview actually calls addSubview.

UIWebView not won't "scrollsToTop" on iOS 7?

I have two UIWebView in a single ViewController in order to preload one in the background for the "next page".
Since opening the project in Xcode 5, these no longer scroll to the top when the status bar is tapped.
The App is otherwise working fine with iOS 7 so I don't know what's wrong. When one of the UIWebView is hidden, I also setScrollsToTop:NO ... so there's clearly something I'm missing.
Any ideas?
I've written a simple class for this specific issue. In my app we're having multiple webviews and scrollviews. This makes it all much easier.
https://gist.github.com/hfossli/6776203
Use this category:
UIView+LogViewHierarchy.h
#import <UIKit/UIKit.h>
#interface UIView (LogViewHierarchy)
-(void) logViewHierarchy;
#end
UIView+LogViewHierarchy.m
#import "UIView+LogViewHierarchy.h"
#implementation UIView (LogViewHierarchy)
-(void) logViewHierarchy
{
NSLog(#"%#%#", NSStringFromClass(self.class), NSStringFromCGRect(self.frame));
[self logSubviews:self depth:1];
}
-(void) logSubviews:(UIView*)view depth:(NSInteger)depth
{
for (UIView *subview in view.subviews) {
if ([subview isKindOfClass:[UIScrollView class]]) {
NSLog(#"%#%#%# - scrollsToTop: %#", [self paddingString:depth], NSStringFromClass(subview.class), NSStringFromCGRect(subview.frame), ((UIScrollView*)subview).scrollsToTop ? #"YES" : #"NO");
} else {
NSLog(#"%#%#%#", [self paddingString:depth], NSStringFromClass(subview.class), NSStringFromCGRect(subview.frame));
}
[self logSubviews:subview depth:depth+1];
}
}
-(NSString*) paddingString:(NSInteger)depth
{
return [#"" stringByPaddingToLength:depth*2 withString:#" " startingAtIndex:0];
}
#end
Then find your app's root view controller and add:
-(void) viewDidAppear:(BOOL)animated
{
[self.view logViewHierarchy];
}
You will be able to see all UIScrollViews and their scrollsToTop properties. When you manage to make your output look like there is only 1 UIScrollView that has scrollsToTop == YES, then your scrollsToTop gesture should work fine.
In my case, logViewHierarchy reported that all your scroll views have scrollsToTop = NO, and you didn't know why, because I explicitly set them to YES.
It turned out that I left this UIScrollView category inside my project, and it overloaded some methods on all my UIScrollViews. When I removed that category from my project, I was able to get correct output from logViewHierarchy. Then I played around with code until I managed to get only one scrollsToTop = YES.

Resources