Update UIView after Locking and Unlocking phone - ios

My app is running an NSURLSession where it downloads a file. However, when the user locks the phone I cannot update the subviews on the screen. They are frozen. I have a method getting called when the phone locks via the app delegate; however, it will not update any subviews.
I have tried placing the updates on main thread or background and nothing works. I simply want to adjust visibility of certain objects but not longer can do that after screen is locked. I hope that is enough info. Any help would be awesome. Thanks guys!
This is what is getting called via the app delegate when the phone is locked
-(void)pauseDownload{
// I want to update the UI!!!!
[session invalidateAndCancel];
bytesSum = 0;
percent = 0;
[HUD hide:YES];
self.downloadButton.hidden = NO;
HUD.progress = percent;
[HUD setLabelText:[NSString stringWithFormat:#"Loading %.0f%%",(percent*100)]];
}
None of the visibility permissions will work and the objects are un responsive. My guess is that I am losing a pointer to the objects some how when the phone is locked. Can I regain them? Am I way off idk?!

Use this in loadView or viewDidLoad:
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(becomeActive)
name:UIApplicationDidBecomeActiveNotification
object:nil];
-(void) becomeActive
{
NSLog(#"ACTIVE");
//
}

You can update UI in viewWillAppear: life cycle view controller method:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// update UI
}
Also, read apple's doc

Once device is lock there is no certain methodology or no way to create the background process or continue download process.
The only possible way can be used is we while during the downloading process if user lock the device & app goes into background downloaded content should be saved. So once when application is again active the downloading process should start from where it stopped.

Related

Resetting sprite node in background

I am having a simple game in which if user goes to background, the game upon starting has to hide the player sprite node.
My code is as follows:
- (void)didMoveToView:(SKView *)view
{
[super didMoveToView:view];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(appDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
}
- (void)appDidEnterBackground:(NSNotification *)notification
{
[self hidePlayerNode];
}
- (void)hidePlayerNode
{
[self.playerNode runAction:[SKAction fadeOutWithDuration:0.0]];
}
The problem is that when the game is launched from background, I can see the player node for a split second and then it disappears. I need to make the player node invisible, the moment it goes to background and user shouldn't see it when the app is relaunched.
I tried with UIApplicationWillResignActiveNotification but the result is the same. Also, I tried running the code inside the selector method by main thread, but same result again.
You are probably seeing the state of your app that was saved as you went into the background.
Apple docs: "When your applicationDidEnterBackground: method returns, the system takes a picture of your app’s user interface and uses the resulting image for transition animations. If any views in your interface contain sensitive information, you should hide or modify those views before the applicationDidEnterBackground: method returns."

How hide or close my app when i reveive a call?

I have a little bug. I'm developing an iOS App.
If i receive a call, my app stays open and the screen for my entering call appears on my app. I would like to close my app if i have a call.
How can i fix that?
Thanks,
J.
The green, in-call status bar is not a bug but a feature. You don't need to close the app when the call comes.
Instead, make sure your views are resized properly when the in-call status bar appears.
As Per Apple Human Interface guidelines
Never quit an iOS app programmatically because people tend to interpret this as a crash.
However, if external circumstances prevent your app from functioning as intended, you need
to tell your users about the situation and explain what they can do about it. Depending on
how severe the app malfunction is, you have two choices.
Display an attractive screen that describes the problem and suggests a correction. A
screen provides feedback that reassures users that there’s nothing wrong with your app. It
puts users in control, letting them decide whether they want to take corrective action and
continue using your app or press the Home button and open a different app
If only some of your app's features are unavailable, display either a screen or an alert
when people use the feature. Display the alert only when people try to access the feature
that isn’t functioning. `
But again you handle your app accordingly when call comes by using the following notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(incomingCall:) name:CTCallStateIncoming object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(callEnded:) name:CTCallStateDisconnected object:nil];
Srinivasan N's answer has the incorrect observer, you'll want to add this observer which will account for all scenarios: phone calls, Personal Hotspot, GPS/navigation, etc.
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(adjustViews:) name:UIApplicationWillChangeStatusBarFrameNotification object:nil];
}
- (void)adjustViews:(NSNotification *)notification
{
NSValue *rectValue = [[notification userInfo] valueForKey:UIApplicationStatusBarFrameUserInfoKey];
CGRect newFrame;
[rectValue getValue:&newFrame];
NSLog(#"Changed frame to: Width: %f, Height: %f", newFrame.size.width, newFrame.size.height);
// Adjust your views here
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

NSNotification not working from another class

Part of an app I'm working on involves putting a blank screen over the current content if the user becomes inactive. As such after x seconds a blank page view controller is opened:
(From within ViewController.m and triggered by detecting an NSNotification from ScreenBlank.m)
UIPageViewController *blankPage = [self.storyboard instantiateViewControllerWithIdentifier:#"BlankPageViewController"];
[self presentViewController:blankPage animated:YES completion:nil];
This blank screen is then removed when a user touches the screen (And thus confirms their activity), like so:
(From inside the touchesBegan callback of ViewController.m)
[self dismissViewControllerAnimated:YES completion:nil];
The problem I'm having, is that I now want to trigger removing this screen blanking elsewhere, such as when the user logs out. This is done by removing a card from a plugged in card-reader, and means that it is called from a separate class (And one that is instantiated from within ActionMgr.m).
The class in question (CardWatcher) is created like so:
CardWatcher *newInstance = [[CardWatcher alloc] init];
[newInstance StartCardChecker];
And that instance of CardWatcher issues a notification when the card is removed, like so:
[[NSNotificationCenter defaultCenter] postNotificationName:#"logout" object:nil];
This notification is then listened for in ViewController, and on being triggered, executes EXACTLY the same code as is used to blank the screenearlier:
[self dismissViewControllerAnimated:YES completion:nil];
By using logging, I have determined that the notification is being received fine, and is executing the dismissViewControllerAnimated code, but for some reason, said code is not actually dismissing the view controller.
The only reason I can think of, is that it is (In the long run) called form within an instance of a class, but even then it's being passed via an NSNotification, and so in my eyes its source should be irrelevant?
Any help would be much appreciated!
It sounds like the notification is not generated on the main thread and you are hence trying to dismiss the page from a secondary thread. Make sure that you are posting the notification on the main thread and not from secondary threads. When a notification triggers UI events, such as this one, the code that manipulates the UI is required to be executed on the main thread.
Delivering Notifications To Particular Threads
Regular notification centers deliver notifications on the thread in
which the notification was posted. Distributed notification centers
deliver notifications on the main thread. At times, you may require
notifications to be delivered on a particular thread that is
determined by you instead of the notification center. For example, if
an object running in a background thread is listening for
notifications from the user interface, such as a window closing, you
would like to receive the notifications in the background thread
instead of the main thread. In these cases, you must capture the
notifications as they are delivered on the default thread and redirect
them to the appropriate thread.
Just try the following code and let me know if it worked for you.
dispatch_async(dispatch_get_main_queue(),^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"logout" object:nil];
});

Is it possible to detect if a user takes a screenshot in iOS? [duplicate]

Is there a notification or other mechanism of being informed that the user is taking a screenshot with the home/power buttons?
I've seen threads about wanting to disable the taking of screenshots, but that's not what I'm looking to do.
I have a photographer client who's concerned that his works will be copied by means of users taking screenshots and I thought that if there was an opportunity to put a watermark across the image before the screenshot was taken, that would allay his fears.
The PictureWasTakenNotification Darwin notification will be sent when the user takes a screenshot. However, this is sent after the screenshot is taken.
(No notifications will be sent before the screenshot was taken.)
Here's a way which might work, although it will totally go against user interface guidelines I'm sure. If you force the user to have their finger on the screen for the image to show then I don't think they can create screenshots. Because as soon as you press the home+lock keys to actually take the screenshot, the screen seems to behave as if there are no fingers touching it. Try taking a screenshot while moving between home screens to see what I mean.
Not a perfect solution by any means but you may be able to work it into your app design if you're really clever without it detracting too much from the user experience (a tough challenge though!). Nevertheless, I believe this may allow you to display artwork/photos without allowing users to take screenshots.
Since iOS 7 the UIApplicationUserDidTakeScreenshotNotification exists. So doing something like this should detect the screenshots:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(userDidTakeScreenshot) name:UIApplicationUserDidTakeScreenshotNotification object:nil];
}
- (void)userDidTakeScreenshot {
// Screenshot taken, act accordingly.
}
Finally, don't forget to remove the observer:
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationUserDidTakeScreenshotNotification object:nil];
}
What's really needed is a notification that is sent before the actual screen capture happens. A delegate method or some other means of giving the app a screenshotting-in-flight opportunity to redraw your content before the grab happens.
And there isn't one.

The correct way to dismiss a MFMailComposeViewController

I'm at my wit's end. I need to dismiss an MFMailComposeViewController when my app transitions to the background and I can't do it. It ends up creating an awkward application state.
Is there a way to handle this programmatically? Perhaps force the view controller to put the email into the Drafts folder and dismiss without animating?
EDIT:
Calls to - dismissModalViewControllerAnimated: don't work as expected.
The awkward application state I'm talking about is my main view being redrawn over top of the email composer when the application returns from the background. The modal is never dismissed and that email composer is never accessible again.
EDIT:
Code in my initializer:
// For compatibility with iOS versions below 4.0
if (&UIApplicationDidEnterBackgroundNotification != NULL)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationDidEnterBackgroundNotification:) name:UIApplicationDidEnterBackgroundNotification object:nil];
}
Code in my background-entry handler:
- (void) applicationDidEnterBackgroundNotification:(NSNotification *)note {
// Do some other stuff here
// According to the docs, calling the method like this closes all
// child views presented modally
[self dismissModalViewControllerAnimated:NO];
}
I have reproduced a simple application with the code you have above. The mail composer is dismissed properly when the application enters the background.
I can only assume therefore that the //Do some other stuff here section of your code is doing too much stuff and the OS is shutting you down before you have chance to dismiss the composer.
According to the docs:
You should perform any tasks relating to adjusting your user interface before this method exits but other tasks (such as saving state) should be moved to a concurrent dispatch queue or secondary thread as needed. Because it's likely any background tasks you start in applicationDidEnterBackground: will not run until after that method exits, you should request additional background execution time before starting those tasks. In other words, first call beginBackgroundTaskWithExpirationHandler: and then run the task on a dispatch queue or secondary thread.
Perhaps you should move your other stuff to a different thread or request extra time? If you remove the other stuff, does the composer dismiss correctly?

Resources