I've got a UIButton (the 'back button') in the upper left corner of an iPad application that dismisses a view controller. I've discovered that if you tap this button slightly too high, you can both activate the button and start to pull down the notifications pane at the same time. When this happens, my -viewWillDisappear gets executed and stops the animations in the view, but the view doesn't actually dismiss. Of course, the notifications pane doesn't come down all the way, so the net result looks like my animations crashed, and that the back button failed as well.
The obvious solution would be to just move the button down a little bit, but as that is undesirable for layout reasons, I'm curious if:
Anyone has ever seen this behavior before.
If it's well-defined behavior, and if so where does Apple describe it.
Are there any known work-arounds?
EDIT: actually looks like less of an issue after all. Turns out it's my -applicationWillResignActive that's getting called, not -viewWillDisappear. Still looks bad, but at least the behavior is well defined. I'm not activating my home button at all, just pulling down the notifications pane.
I have done an UIViewController which has a timed animation (like a banner ad) going on, and bringing the notification pane down does not stop it until the pane is fully disclosured.
Maybe you have to deal with your animations on -applicationWillResignActive: and -applicationDidBecomeActive:, like pausing and resuming them.
You can receive those notifications directly on your UIViewController (instead of dealing with them on you AppDelegate) by adding the following code to your -viewDidLoad:
// Add observers
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(pauseAnimations:)
name: UIApplicationWillResignActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(resumeAnimations:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
Related
How can I be notified when the iOS Control Center is being opened?
UIApplicationWillResignActiveNotification isn't good enough since this notification is sent also when the Notifications Center is opened, alert view appeared and other possible scenarios.
I was sure this is not possible, but QuizUp app is notified when the user open the Control Center while the user is on middle of a gameplay to prevent cheating the game.
Thanks
Hey there I did a lot of trial and error investigation and came up with a solution that turns out being very reliable. It works in all orientations and both in fullscreen (no statusbar) and in regular mode. AAWindow is a subclass of UIWindow and you can find it on GitHub.
The way I accomplished this is by overriding sendEvent in UIWindow, separating out TouchEvents from the other events and checking whether touches occur in the bottom 10 percent of the screen (which is the part that can open Control Center). If there are touches and applicationWillResignActive is called within a timespan of .5 seconds (with statusbar) or 3 seconds (without statusbar) you can be very sure that this is because of Control Center being opened. Then a NSNotification is being fired and you can react to that anywhere in the application.
I tested a UIPanGestureRecognizer approach (with and without the status bar visible—changes if the little pull tab comes up instead of control center) along with watching for the applicationWillResignActive notification, and I couldn't reliably know if control center was opened. If the pan was slow enough the gesture recognizer would trigger first, but it's definitely easy to swipe up fast enough to trigger control center and bypass the gesture recognizer firing at all.
Attempting to check if the app goes from applicationWillResignActive and then to applicationDidBecomeActive would be a pretty reliable way to know if the app entered and exited one of a couple states (control center, notification center, answering a phone call, etc), but telling the difference between say notification and control center is impossible this way.
TL;DR: I don't think there is a reliable or accurate way to tell if control center was opened, but QuizUp may be doing something interesting to fake it, and I am open to being wrong!
When Control centre is opened the cycle isn't completed. Means only the method
applicationDidResignActivity will be called but applicationDidEnterBackground won't be called. When app is minimized both methods will be called. Here you can differentiate.
I am developing an iPad app. I allow both landscape and portrait mode. My UI is fine in portrait mode but when I change it to landscape mode, my UI gets messed up. I saw some SO posts related to this and I added following code in initWith... in my UIView.
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(abc)
name:UIDeviceOrientationDidChangeNotification
object:nil];
My UI is working fine in portrait mode after doing this. When I change it to landscape mode, my UI is fine. But after I change it back into portrait mode, my app crashes. I read some posts on SO related to app crashing an got to know about instruments. I enabled zombies and found that a message is being sent to already released object and this message is coming from NSNotificationCenter.
Is there something else that I need to handle apart from registering my device ? Also, is there any way where in I can change the implementation from UIView to UIViewController and implement the methods that UIViewController has regarding device orientation ? Please let me know the steps I need to follow in order to get this done. Thanks!
Where are you registering for the notifications? You need to remove the observer when you are about to change orientations (either in prepForSegue or willAnimateRotationToInterfaceOrientation depending on however you've got your setup) in order prevent messaging a no longer valid object. You also don't want to pile up several notifications if your registering in viewDidAppear/viewWillAppear.
Remove the observer using:
[[NSNotificationCenter defaultCenter] removeObserver:self];//removes all notifications for that object (the way I've used it before)
or if you want to be specific, do something like:
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice];//remove just that notification
The UIViewController class has several methods that deal with changes in orientation. See the docs for a discussion of those methods.
One method you should look into is viewWillLayoutSubviews. This is a common place to perform manual view layout. This is called anytime the view controller's orientation changes.
Using these methods is much more common than registering for device orientation change notifications. Based on your statements about the crash, a possible issue is that you never remove the observer that you add. For every call to addObserver there must be a corresponding call to removeObserver. Otherwise the observer is called even if it has long gone away. And this results in the crash you describe.
During an active VOIP call, my app is put into the background when an incoming cellular call is received and answered. If, while on the cellular call, I bring my app back to the foreground the app view appears but is unresponsive. The "Touch to return to call" banner appears at the top of the view in green but the app view appears as if there is a darker transparent window overlaid on top of it preventing the view from receiving input. If I put my app into the background, bring another app to the foreground and then bring my app back to the foreground everything works as expected so the problem seems to be specific to active cell calls and/or the green banner only? In Settings->Notifications->Phone I tried turning Notification Center OFF and Alert Style NONE in the hopes of removing the banner to see if the problem still exists but these settings do not effect that banner. In addtion to the App window appearing to have a transparent window overlaid on it, if I touch the window I'm able to drag the entire app window (or view) in all directions (up down side to side) and it has a bounce effect (like tableview vertical scroll) when I release it.
If I dont know the problem I cannot fix it (:
Thanks..
Are you sure there's no view being added on top your view which might be intercepting all your events? My second guess would've been that your app received a memory warning and unloaded a bunch of views. However, that's not very likely since you still see all the views.
I don't know what you really mean to "bring your app back to the foreground",but I can tell you for sure that you cannot call in the same thread the UI and the incoming call, so for situations like this when you want to render some view during a call you can try something like this:
public void InvokeGUIThread(Action action)
{
Dispatcher.Invoke(action);
}
For example if you want to set a text in a textblock do something like this:
InvokeGUIThread(() =>
{
textBlockSome.Text = e.Item.ToString();
});
I have my store all setup, everything is working perfectly.
What i'm trying to do now is when they click on a button to buy something from my app, i'm displaying a custom UIActivityIndicator type thing to show the users that things are actually loading (and to stop them from going back in case the alert takes 10+ secs to show up).
I have a timeout set to perform after a 30s delay to hide the ActivityIndicator incase the store isn't responding so the users won't be stuck waiting forever.
All this is working fine.
The problem is when the 'Confirm Your In App Purchase' Alert is displayed, i'm not sure how to get notified that it appeared so i can hide the ActivityIndicator I have still running in the back.
There are methods to detect when the user hits Cancel or Buy which I have but I would like to hide the ActivityIndicator before they hit one so the users don't see it in the background while they read it.
Did I overlook a delegate that would work for this?
Or will I have to write something custom to make this work the way I want?
Thanks!
I also tried implementing the UIAlertViewDelegate with this method however it doens't catch the In-App Purchase alert views :(
- (void)didPresentAlertView:(UIAlertView *)alertView;
In case anyone else is interested in a solution I made up.
When you call load and start connecting to your store you can add an observer to catch when your phone will resign being active. This way when the In App alert appears the method you choose gets called and you can cancel your activity monitor.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(inAppAlertAppeared:)
name:UIApplicationWillResignActiveNotification
object:nil];
Check the following link
http://www.raywenderlich.com/2797/introduction-to-in-app-purchases
it may help you
I have a tabBarController containing three tabs. One tab is a settings tab, it has three UISwtch's which are contained in a UITableView, and it stores the data in [NSUserDefaults standardUserDefaults]. I'm testing everything a user could possibly do and have found a small problem. When the settings tab is in the foreground and I exit the app, enter the main settings for the phone, alter the settings for my app, exit settings then restart my app, the settings tab is still in the foreground but the toggle switches do not reflect the changes made in the previous step. If i switch to another tab then back to my settings tab the changes are now reflected.
I've tried everything, viewWillAppear, viewDidAppear, [theTtableView reloadData], nothing works. The strange thing is the exact same functions are called when it resumes and the settings tab is in the forground, as when another tab is in the foreground then I select the settings tab. I just can't get it to refresh, even though viewDidAppear and viewWillAppear are both being called on the settings controller.
I know is probably unlikely a user will be in the in app settings tab, then exit and go to the phone settings tab to make a change, then back to the app, but it's driving me nuts and I need to fix this.
I've tried every suggestion I could find here, still can't make it work.
Any ideas?
Thanks
Call this
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(refreshViews) name:UIApplicationWillEnterForegroundNotification object:nil];
in your view controller's initialization (replace refreshViews with selector of the method you refresh your switches to reflect the actual values in).
Don't forget to [[NSNotificationCenter defaultCenter] removeObserver:self] in dealloc.
Alternatively you can register for the notification in viewDidLoad or viewWillAppear and unregister in viewDidUnload orviewWillDisapper respectively.
Did you try putting some refresh code in applicationWillResumeActive or applicationWillEnterForeground in your UIApplicationDelegate?