applicationWillResignActive gets called but doesn't call code - ios

I'm trying to pause my game when the app gets interrupted! (like Phonecalls, SMS, etc.)
I created a pause menu in my Game Viewcontroller (rush_gamemode).
When I press the pause Button in the game everything works just fine.
If I call the method via "applicationWillResignActive" in AppDelegate it does work kind of.
Here's my Code:
in rush_gamemode.h
-(void)goIntoPause;
in rush_gamemode.m
-(void)goIntoPause
{
NSLog(#"RUSH goIntoPause was called!");
self.Button_Pause.hidden = YES;
//--------pause timer-------//
if (self.timerStart) {
timerWasStarted = YES;
self.oldTimeNumber = self.timeNumber;
[self.timerStart invalidate];
self.timerStart = nil;
}
//--------set up pause menu--------//
self.transparent_subview_background.alpha = 0;
self.Pause_Subview.hidden = NO;
self.Pause_Subview.backgroundColor = [UIColor clearColor];
[UIView beginAnimations:NULL context:NULL];
[UIView setAnimationDuration:.75];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
[self.transparent_subview_background setAlpha:0.75];
[UIView commitAnimations];
}
in AppDelegate.h
#class rush_gamemode;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
rush_gamemode* rush;
}
in AppDelegate.m I imported "rush_gamemode.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
rush = [[rush_gamemode alloc] init];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
[rush goIntoPause];
}
So when I start the App, and press the HomeButton (e.g) or get a Phone call, the console shows the NSLog ("RUSH goIntoPause was called!") but doesn't do anything else..
What am I doing wrong here?
cheers, Niklas

Related

Overlay an image when app is inactive

I'm using these code to
1) overlay an image when the app is inactive (double tap the home button twice).
2) Remove the image when the app is active (reopen the app)
In appdelegate.h file:
#property (nonatomic, strong) UIImageView *splashScreenImageView;
In appdelegate.m file:
- (void)applicationWillResignActive:(UIApplication *)application
{
UIImage *splashScreenImage = [UIImage imageNamed:#"BackgroundScreenCaching"];
_splashScreenImageView = [[UIImageView alloc] initWithImage:splashScreenImage];
[self.window addSubview:_splashScreenImageView];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if(_splashScreenImageView != nil) {
[_splashScreenImageView removeFromSuperview];
_splashScreenImageView = nil;
}
}
Problem:
However, SOMETIME when pressing the home button twice, the iOS still caches the app screen with sensitive information instead of the overlay image in iOS 11. Tested no issue in iOS10.
Updated
Issue still persist after changing to this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
BOOL result = [super application:application didFinishLaunchingWithOptions:launchOptions];
...
UIImage *splashScreenImage = [UIImage imageNamed:#"BackgroundScreenCaching"];
_splashScreenImageView = [[UIImageView alloc] initWithImage:splashScreenImage];
[_splashScreenImageView setFrame:self.window.bounds];
return result;
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
if(_splashScreenImageView != nil) {
[_splashScreenImageView removeFromSuperview];
}
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
[self.window addSubview:_splashScreenImageView];
}
I found a tricky way and it works with iOS 11 or iOS 10.
In Appdelegate.m file:
#implementation AppDelegate {
UIImageView *splashScreenImageView;
UIViewController *viewController;
}
Add this code in didFinishLaunchingWithOptions to set image and update frame
splashScreenImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
splashScreenImageView.image = [UIImage imageNamed:#"BackgroundScreenCaching"];
Implement this method for getting topmost view controller
- (UIViewController *)topViewController{
return [self topViewController:[UIApplicationsharedApplication].keyWindow.rootViewController];
}
- (UIViewController *)topViewController:(UIViewController *)rootViewController
{
if (rootViewController.presentedViewController == nil) {
return rootViewController;
}
if ([rootViewController.presentedViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
return [self topViewController:lastViewController];
}
UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
return [self topViewController:presentedViewController];
}
Now in applicationWillResignActive method first get the top viewController and set splashScreenImageView on that view as subview
- (void)applicationWillResignActive:(UIApplication *)application {
viewController = [self topViewController];
[viewController.view addSubview:splashScreenImageView];
}
Finally in applicationDidBecomeActive when app open first remove the overlay image and open app
- (void)applicationDidBecomeActive:(UIApplication *)application {
[splashScreenImageView removeFromSuperview];
}
This tricks will work.
Your code should work fine ,
May be your app didn't get time to alloc your imageView on time when applicationWillResignActive called
and you are re-creating object every time . with [UIImageView alloc] initWithImage
So my suggestion is put this code in didFinishLaunching
UIImage *splashScreenImage = [UIImage imageNamed:#"BackgroundScreenCaching"];
_splashScreenImageView = [[UIImageView alloc] initWithImage:splashScreenImage];
and just add subview on UIWindow and remove it when applicationDidBecomeActive
Also bring _splashScreenImageView to front !!
Hope it may solve your problem
Good Luck
UPDATE
to add in main queue
dispatch_async(dispatch_get_main_queue(), ^{
[self.window addSubview:_splashScreenImageView];
[self.window bringSubviewToFront:_splashScreenImageView];
});
to remove in main queue
dispatch_async(dispatch_get_main_queue(), ^{
[_splashScreenImageView removeFromSuperview];
});
UPDATE 2
according to https://developer.apple.com/library/content/qa/qa1838/_index.html
and
https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StrategiesforHandlingAppStateTransitions/StrategiesforHandlingAppStateTransitions.html
Prepare for the App Snapshot
Shortly after an app delegate’s applicationDidEnterBackground: method returns, the system takes a snapshot of the app’s windows. Similarly, when an app is woken up to perform background tasks, the system may take a new snapshot to reflect any relevant changes. For example, when an app is woken to process downloaded items, the system takes a new snapshot so that can reflect any changes caused by the incorporation of the items. The system uses these snapshot images in the multitasking UI to show the state of your app.
If you make changes to your views upon entering the background, you can call the snapshotViewAfterScreenUpdates: method of your main view to force those changes to be rendered. Calling the setNeedsDisplay method on a view is ineffective for snapshots because the snapshot is taken before the next drawing cycle, thus preventing any changes from being rendered. Calling the snapshotViewAfterScreenUpdates: method with a value of YES forces an immediate update to the underlying buffers that the snapshot machinery uses.
Try to present temp view controller applicationDidEnterBackground as done in demo of Apple
I fix your bug like this:
#import "AppDelegate.h"
#interface AppDelegate () {
UIImageView *test ;
}
#end
#implementation AppDelegate
- (void)applicationDidEnterBackground:(UIApplication *)application {
UIImage *splashScreenImage = [UIImage imageNamed:#"ic_target_black"];
test = [[UIImageView alloc] initWithImage:splashScreenImage];
[self.window addSubview:test];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
if (test) {
[test removeFromSuperview];
}
}
#end
Do this two simple steps to set your black image when double click the app and it is in recent apps list. And remove the black image when the application becomes active.
#interface AppDelegate (){
UIImageView *test ;
}
- (void)applicationWillResignActive:(UIApplication *)application {
UIImage *splashScreenImage = [UIImage imageNamed:#"ss.png"];
test = [[UIImageView alloc] initWithImage:splashScreenImage];
[self.window addSubview:test];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
if (test) {
[test removeFromSuperview];
}
}

iOS 11: Is it possible to block screen recording?

I have an app which plays video, and I don't want people to use the new iOS-11 feature to record these videos and make them public. That feature is described here.
I could not find any documentation regarding an option for my app to prevent users from recording it.
Can anybody please guide me to anything related to this?
Thank you!
I am publishing here the official response from Apple Developer Technical Support (DTS):
While there is no way to prevent screen recording, as part of iOS 11, there are new APIs on UIScreen that applications can use to know when the screen is being captured:
UIScreen.isCaptured Instance Property
UIScreenCapturedDidChange Notification Type Property
The contents of a screen can be recorded, mirrored, sent over AirPlay, or otherwise cloned to another destination. UIKit sends the UIScreenCapturedDidChange notification when the capture status of the screen changes.
The object of the notification is the UIScreen object whose isCaptured property changed. There is no userInfo dictionary. Your application can then handle this change and prevent your application content from being captured in whatever way is appropriate for your use.
HTH!
The feature is available on and above iOS11. Better keep it inside didFinishLaunchingWithOptions
Objective-C syntax
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (#available(iOS 11.0, *)) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(screenCaptureChanged) name:UIScreenCapturedDidChangeNotification object:nil];
}
return YES;
}
-(void)screenCaptureChanged{
if (#available(iOS 11.0, *)) {
BOOL isCaptured = [[UIScreen mainScreen] isCaptured];// will keep on checking for screen recorder if it is runnuning or not.
if(isCaptured){
UIView *colourView = [[UIView alloc]initWithFrame:self.window.frame];
colourView.backgroundColor = [UIColor blackColor];
colourView.tag = 1234;
colourView.alpha = 0;
[self.window makeKeyAndVisible];
[self.window addSubview:colourView];
// fade in the view
[UIView animateWithDuration:0.5 animations:^{
colourView.alpha = 1;
}];
}else{
// grab a reference to our coloured view
UIView *colourView = [self.window viewWithTag:1234];
// fade away colour view from main view
[UIView animateWithDuration:0.5 animations:^{
colourView.alpha = 0;
} completion:^(BOOL finished) {
// remove when finished fading
[colourView removeFromSuperview];
}];
}
} else {
// Fallback on earlier versions
// grab a reference to our coloured view
UIView *colourView = [self.window viewWithTag:1234];
if(colourView!=nil){
// fade away colour view from main view
[UIView animateWithDuration:0.5 animations:^{
colourView.alpha = 0;
} completion:^(BOOL finished) {
// remove when finished fading
[colourView removeFromSuperview];
}];
}
}
}

UIWindow's makeKeyAndVisible and background task

I've add the background task feature to my application. Here is my app delegate
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]];
[self.window setBackgroundColor:[UIColor blackColor]];
if (application.applicationState != UIApplicationStateBackground) {
// Application is launch in because user tap the app icon or from springboard
if ([application respondsToSelector:#selector(setMinimumBackgroundFetchInterval:)]) {
[application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
}
} else {
// Application is launch in background mode
}
RootViewController *rootViewController = [[RootViewController alloc] initByDevice];
[self.window setRootViewController:rootViewController];
[self.window makeKeyAndVisible];
return YES;
}
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[DataManager instance] updateDataWithMaxAttempt:5 block:^(BOOL success, NSArray *newData) {
if (success) {
if ([newData count] > 0) {
completionHandler(UIBackgroundFetchResultNewData);
} else {
completionHandler(UIBackgroundFetchResultNoData);
}
} else {
completionHandler(UIBackgroundFetchResultNoData);
}
}];
}
And this is my root view controller
// RootViewController.m
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(#"Did appear");
// Do something that I want it to happen only when the application is visible to user
}
When the user tap the app icon, application works like what I expected. I see "Did appear" in console and stuff is happening after that like I expected.
But when the application awake to perform background task (which not visible to user) the RootViewController's viewDidAppear still getting call because of this line
[self.window makeKeyAndVisible];
By calling makeKeyAndVisible, it makes RootViewController visible even though it's only awake for background task. To fix this, I have to move this line to applicationDidBecomeActive
- (void)applicationDidBecomeActive:(UIApplication *)application {
[self.window makeKeyAndVisible];
}
As a result, the RootViewController's viewDidAppear now being call only when the application is in foreground (visible to user). But, my concern is, when application is in device memory (either active or inactive) applicationDidBecomeActive will be call several times.
user launch app
application become active again from springboard
device unlock
finish call
Is there any issue if I call UIWindow's makeKeyAndVisible several times during the application life cycle?
You can easily ensure that makeKeyAndVisible only happens once: wrap it.
if (!self.window.keyWindow) {
[self.window makeKeyAndVisible;
} else if (self.window.hidden) {
self.window.hidden = NO;
}

MMDrawerController unrecognized selector

I'm trying to setup a siderbar navigation menu for my app. I'm using the MMDrawerController lib, but I'm running into an issue. I've added a button and use these methods to call the sidebar:
-(void)setupLeftMenuButton{
MMDrawerBarButtonItem * leftDrawerButton = [[MMDrawerBarButtonItem alloc] initWithTarget:self action:#selector(leftDrawerButtonPress:)];
[self.navigationItem setLeftBarButtonItem:leftDrawerButton animated:YES];
}
-(void)leftDrawerButtonPress:(id)sender{
[self.mm_drawerController toggleDrawerSide:MMDrawerSideLeft animated:YES completion:nil];
}
I'm using a Navigation Controller with a View Controller attached in which I'm calling this method. This viewcontroller is called ViewController2.
Whenever I press the button to pull out the sidemenu, it crashes and returns this error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ViewController2 mm_drawerController]: unrecognized selector sent to instance 0x835b440'
What am I doing wrong?
edit:
AppDelegate.h
#import "AppDelegate.h"
#import "MMDrawerController.h"
#import "ViewController2.h"
#import "MMLeftSideDrawerViewController.h"
#import "MMRightSideDrawerViewController.h"
#import "MMDrawerVisualState.h"
#import "MMDrawerVisualStateManager.h"
#import <QuartzCore/QuartzCore.h>
#interface AppDelegate ()
#property (nonatomic,strong) MMDrawerController * drawerController;
#end
#implementation AppDelegate
-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
UIViewController * leftSideDrawerViewController = [[MMLeftSideDrawerViewController alloc] init];
UIViewController * centerViewController = [[ViewController2 alloc] init]; // MAYBE SOMETHING WRONG HERE?
UIViewController * rightSideDrawerViewController = [[MMRightSideDrawerViewController alloc] init];
UINavigationController * navigationController = [[UINavigationController alloc] initWithRootViewController:centerViewController];
[navigationController setRestorationIdentifier:#"MMCenterNavigationControllerRestorationKey"];
self.drawerController = [[MMDrawerController alloc]
initWithCenterViewController:navigationController
leftDrawerViewController:leftSideDrawerViewController
rightDrawerViewController:rightSideDrawerViewController];
[self.drawerController setRestorationIdentifier:#"MMDrawer"];
[self.drawerController setMaximumRightDrawerWidth:200.0];
[self.drawerController setOpenDrawerGestureModeMask:MMOpenDrawerGestureModeAll];
[self.drawerController setCloseDrawerGestureModeMask:MMCloseDrawerGestureModeAll];
[self.drawerController
setDrawerVisualStateBlock:^(MMDrawerController *drawerController, MMDrawerSide drawerSide, CGFloat percentVisible) {
MMDrawerControllerDrawerVisualStateBlock block;
block = [[MMDrawerVisualStateManager sharedManager]
drawerVisualStateBlockForDrawerSide:drawerSide];
if(block){
block(drawerController, drawerSide, percentVisible);
}
}];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window setRootViewController:self.drawerController];
return YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder{
return YES;
}
- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder{
return YES;
}
- (UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
{
NSString * key = [identifierComponents lastObject];
if([key isEqualToString:#"MMDrawer"]){
return self.window.rootViewController;
}
else if ([key isEqualToString:#"MMCenterNavigationControllerRestorationKey"]) {
return ((MMDrawerController *)self.window.rootViewController).centerViewController;
}
else if ([key isEqualToString:#"MMLeftSideDrawerController"]){
return ((MMDrawerController *)self.window.rootViewController).leftDrawerViewController;
}
else if ([key isEqualToString:#"MMRightSideDrawerController"]){
return ((MMDrawerController *)self.window.rootViewController).rightDrawerViewController;
}
return nil;
}
#end
Take a look at the example have you tried something like in case you are using navigation
(or swapping view in case you are not)
[(UINavigationController*)self.mm_drawerController.centerViewController pushViewController: animated:YES];

Using iAds on iPad crashes after huge number of calls to bannerView:didFailToReceiveAdWithError:

I have an app that uses a xib defined AdBannerView. If the app runs on an iPhone (4 or 5) everything works as expected, ads get shown, banners get hidden / shown etc.
However if the app is run on an iPad it crashes after repeatedly failing to receive the ad. Examining the call stack shows repeated calls to bannerView:didFailToReceiveAdWithError:
Watching allocations while its running on an iPad shows continuous memory growth until the crash.
Messing with the network connectivity doesn't seem to alter the fact that it works on an iPhone but not on an iPad.
I read this SO question which instead of using a AdBannerView in the xib it creates it on the fly and then releases it appropriately when the ad fails to load.
EDIT:
I changed the devices setting in the project file from iPhone to Universal. The app now does not crash but of course all the views are now 'messed up'. So one option for a fix would be to implement the iPad idiom throughout the app.
My questions are -
What is going on? No, really! I'm confused as to why there is differing behaviour between devices.
Should I look to creating the AdBannerView programmatically? That kind of feels defeatist.
How can I fix this behaviour?
Here is the code
#pragma mark ADBannerViewDelegate
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
[self showBanner];
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
[self hideBanner];
}
- (void)bannerViewActionDidFinish:(ADBannerView *)banner
{
[self hideBanner];
}
#pragma mark ADBanner helpers
- (void)hideBanner
{
CGRect hiddenFrame = self.bannerDisplayFrame;
hiddenFrame.origin.y = self.view.frame.size.height;
[UIView animateWithDuration:0.3f
animations:^{
[self.adBannerView setFrame:hiddenFrame];
}
completion:^(BOOL finished)
{
if (finished)
{
[self.adBannerView setAlpha:0.0f];
}
}];
}
- (void)showBanner
{
[self.adBannerView setAlpha:1.0f];
[UIView animateWithDuration:0.3f
animations:^{
[self.adBannerView setFrame:self.bannerDisplayFrame];
}
completion:^(BOOL finished)
{
if (finished)
{
[NSTimer scheduledTimerWithTimeInterval:60.0f target:self selector:#selector(hideBanner) userInfo:nil repeats:NO];
}
}];
}
It looks like you are creating new iAD banner views every time, the suggested way is to use a shared one throughout the whole app. This might be the reason of continuous memory growth in your app and you will definitely end up with a warning from apple servers if you request ads too many times. Have a look at here in Apple's documentation for more details iAD Best Practices
This is how I implemented shared adbannerview, it might be of help.
AppDelegate.h
#property (nonatomic, strong) ADBannerView *adBanner;
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
adBanner = [[ADBannerView alloc] initWithFrame:CGRectZero];
adBanner.delegate = self;
adBanner.backgroundColor = [UIColor clearColor];
adBanner.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin;
...
}
prefix.pch or better in a header file included in prefix.pch
#define SharedAdBannerView ((AppDelegate *)[[UIApplication sharedApplication] delegate]).adBanner
And I have a implemented a uiviewcontroller category to handle iADs
#implementation UIViewController (SupportIAD)
-(void)bannerViewDidLoadAd:(ADBannerView *)banner
{
SharedAdBannerView.hidden = FALSE;
}
-(void) bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
SharedAdBannerView.hidden = TRUE;
}
//This method adds shared adbannerview to the current view and sets its location to bottom of screen
//Should work on all devices
-(void) addADBannerViewToBottom
{
SharedAdBannerView.delegate = self;
//Position banner just below the screen
SharedAdBannerView.frame = CGRectMake(0, self.view.bounds.size.height, 0, 0);
//Height will be automatically set, raise the view by its own height
SharedAdBannerView.frame = CGRectOffset(SharedAdBannerView.frame, 0, -SharedAdBannerView.frame.size.height);
[self.view addSubview:SharedAdBannerView];
}
-(void) removeADBannerView
{
SharedAdBannerView.delegate = nil;
[SharedAdBannerView removeFromSuperview];
}
#end
And now in every viewcontroller that is going to display iADs, import the category and in viewDidLoad:
- (void)viewDidLoad
{
...
[self removeADBannerView];
[self addADBannerViewToBottom];
...
}
To prevent the views getting messed up, try turning "Auto Layout" off.
Xcode 4.5 corrupting XIBs?
I have solved this problem.
The root of the problem is that iPad's view property of iPad's UIViewController looping recursively.
All you need is to break infinite call.
In my case I just add these lines:
if (_banner.alpha == 0)
{
return;
}
in banner hiding method.
I guess you have crash here:
hiddenFrame.origin.y = self.view.frame.size.height;
Anyway, its not a good approach do not check property before changing.

Resources