I am creating an app with functionality like a stopwatch. When the app moves to the background, iOS takes a snapshot, and when it moves back into the foreground it uses that snapshot for the animation while switching back to the app.
This means that if the app was backgrounded for 10 seconds, the stopwatch will have the wrong time (by 10 seconds) displayed during the opening animation.
Is there some way to stop iOS taking this snapshot, or stop iOS from using it when the app moves back to the foreground?
You can not stop iOS from taking snapshot.
But you can display and hide a temporary view using below notifications :
UIApplicationDidEnterBackgroundNotification
UIApplicationWillEnterForegroundNotification
The temporary view will be then taken as the snapshot.
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(displayTempView) name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(hideTempView) name:UIApplicationWillEnterForegroundNotification object:nil];
- (void) displayTempView {
tempWebView.hidden = NO;
}
- (void) hideTempView {
tempWebView.hidden = YES;
}
Hope it helps.
Related
I bult an iOS app and in -(void)viewDidLoad I parse data from web, and display it on load. But often when I open my app it displays old data(app loads fast) and I need to kill it and open it again, after that it parses data and shows new. Why is that happening?
It doesn't work that way because viewDidLoad is only called once, when the view is created. After backgrounding and returning, your view still exists.
If you want to reload your data whenever the app returns from the background, you need to either override applicationDidBecomeActive: in your UIApplicationDelegate implementation, or you need to listen for the appropriate notification:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
// reload your data here.
}
Don't forget to remove yourself as an observer when you no longer need the notification.
I am just coding my first iOS app using a today widget (using Swift). I was wondering if there is a function that is called whenever my app comes back to the foreground after dismissing the notification center.
I know I can use an Observer to check for UIApplicationWillEnterForegroundNotification but my function does not get called when pulling down the notification center while using my app and dismissing it again.
My problem is simple:
It is quite unlikely users will pull down the notification center to manipulate data I am using in the app, but I still have to consider what happens if they do. The user is supposed to be able to save his current location by pressing the today widget button.
If that happens while using my app, the app won't check for new data.
I used the following code for determining if the notification center was opened during the application's run time:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
{
BOOL notificationCenterCurrentlyDisplayed;
}
- (void) viewDidLoad
{
[super viewDidLoad];
notificationCenterCurrentlyDisplayed = false;
NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter addObserver:self selector:#selector(onNotificationCenterDisplayed) name:UIApplicationWillResignActiveNotification object:nil];
[defaultCenter addObserver:self selector:#selector(onNotificationCenterDismissed) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void) onNotificationCenterDisplayed
{
notificationCenterCurrentlyDisplayed = true;
NSLog(#"Notification center has been displayed!");
}
- (void) onNotificationCenterDismissed
{
// Reason for this check is because once the app is launched the UIApplucationDidBecomeActiveNotification is called.
if (notificationCenterCurrentlyDisplayed)
{
notificationCenterCurrentlyDisplayed = false;
NSLog(#"Notification center has been dismissed!");
}
}
#end
Also the notification center was displayed method will also be called when the user decides to close the application into the background.
I am implementing a VideoRecorder using the AVCaptureSession.
I am starting AVCaptureSession at viewWillAppear and tearing it down at viewWillDisappear on recommendation of this question AVCaptureSession fails when returning from background
.
Now when the Video is Recording and the app goes to background I want to stop recording and pause the capture session. But each time the app comes to foreground at this point I get one of the following
Capture Session is not paused but recording and the Preview Layer keeps updating
Capture Session provides Preview Layer with black-screen at this point app may or may not crash.
Any suggestions on handling the AVCaptureSession at this point. I would like to just show the last frame recorded on the previewLayer, once recording stops.
I have encountered a similar situation and in my experience I have found that viewWillDisappear: doesn't get called. I'm really not sure why, but I solved it by subscribing for notifications when the app goes inactive. Here's an example:
In viewWillAppear:
// Detect this for ending recording
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(appInactive:) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];
And the appropriate callback method:
- (void)appInactive:(NSNotification *)notification {
NSLog(#"App going inactive, stopping recording...");
taskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{
[[UIApplication sharedApplication] endBackgroundTask:taskId];
taskId = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
question.prepTimeRemaining = [prepEndTime timeIntervalSinceNow];
// Stop camera stuff
if (recording)
[self stopRecording]; // Method to handle shutting down the session, any other cleanup, etc.
// End task
[[UIApplication sharedApplication] endBackgroundTask:taskId];
taskId = UIBackgroundTaskInvalid;
});
}
In viewWillDisappear:
[[NSNotificationCenter defaultCenter] removeObserver:self];
I immediately move to the next view when I detect this, so I'm not sure what it leaves behind on the preview layer, but I suspect it would do what you want. Hope this helps!
This is late but I was experiencing some of the same. In order to get around the problem you first have to realize ViewWillAppear and ViewWillDisappear are strictly for in app transitions from one View Controller to another. They don't work for foreground to background and back again transitions. I used a similar fix above:
//application became active
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationEnteredForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
//application went into background
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationBecameActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
In the selector methods just stop and start your camera session and as the other stackoverflow post suggest, it would be a good idea to lazily instantiate your avcapturesession so that your app is memory conservative
How to use UIApplicationDidBecomeActiveNotification?
Should I declare it in viewDidLoad or viewWillAppear to reload data when coming from background to foreground.
Does UIApplicationDidBecomeActiveNotification gets called only when app comes from background to foreground?
Please help.
Thanks.
Sometimes it is useful to have a listener of UIApplicationDidBecomeActiveNotification when you need to make some action in your view controller on wake up from background (in case you entered to background with this view controller on-screen). In such wake up viewWillAppear will not be triggered!
Example of use:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(someMethod) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)someMethod
{
<YOUR CODE AT WAKE UP FROM BACKGROUND>
}
Of course, you can also implement all you need at your app delegate class life cycle.
You get this notification if your app was interrupted by a phone call or push notification. Generally, if your application is getting active on screen after interruption.
You can register any class, that is loaded in memory by the moment application will become active as observer to this notification.
Use following code in viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(someMethod:)
name:UIApplicationDidBecomeActiveNotification object:nil];
Use someMethod to handle this notification. And don't forget to remove this class as observer in dealloc:
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationDidBecomeActiveNotification
object:nil];
The OP asked about system notifications fired when the app is backgrounded and then foregrounded again. The Notification designed to handle this situation is the UIApplicationDidEnterBackgroundNotification and UIApplicationWillEnterForegroundNotification. If you want a notification that fires for a wider range of situations, such as when you have a system notification, take a phone call, a SMS comes in, or you slide up the control pane, as well as being backgrounded then you will want the UIApplicationWillResignActiveNotification and UIApplicationDidBecomeActiveNotification. It's important to recognize that these are different, since you might only need to react if your app is backgrounded, and not for other scenarios.
I want to use UIWebView to load URL and play vedios. When I press done button in MediaPlayer control on the UIWebView, I want to do something.
My Question is, in this case can it be OK, or does the UIWwebView has a delegate method to do after pressing done button?
The "Done" button only shows up in full screen mode. You can detect the end of full screen mode by observing the #"UIMoviePlayerControllerDidExitFullscreenNotification" mode:
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayerDidExitFullscreen:)
name:#"UIMoviePlayerControllerDidExitFullscreenNotification"
object:nil];
}
- (void)viewDidUnload
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)moviePlayerDidExitFullScreen:(NSNotification *)notification
{
// This is where you do whatever you want because the user pressed "Done".
}
The UIMoviePlayerControllerDidExitFullscreenNotification is not documented, so I don't know if it will pass App Store review. If you're not planning to distribute via the App Store, it shouldn't matter.