I've taken over a project that handles which screen to show first in the "applicationDidBecomeActive" function inside the AppDelegate. This has been causing problems because whenever the app asks for a permission sometimes, not all, it will trigger this block of code and send the user to the incorrect screen. I'm not sure what to do since I've never encountered this before. Any ideas why this is occurring or ways to circumvent this? I've tried adding a flag variable, however, that doesn't seem to work consistently because it looks like it gets un-set before the applicationDidBecomeActive is triggered.
When system notifications such as Permissions are presented, the application is sent to background, or becomes "inactive". When the Permission notification is dismissed, the application becomes "active" again. This would explain why didBecomeActive is triggered.
https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622956-applicationdidbecomeactive
I've taken over a project that handles which screen to show first in the "applicationDidBecomeActive" function inside the AppDelegate... Any ideas why this is occurring or ways to circumvent this?
The simple answer is: don't do that work in applicationDidBecomeActive(). As you've seen, the application can become inactive and then active again while the app remains in the foreground, so that's not the right state transition for what you're doing. Identify the app state transitions where you really do want to choose a screen. For example, you might want to do it when the app launches, and also when it transitions from background to foreground, so you could use application(_:didFinishLaunchingWithOptions:) and applicationWillEnterForeground(_:). (Obviously, you don't want to put the same code in both places, so put it in a separate method and just call it from those two methods.)
Apple has a document that covers this very topic: Managing Your App's Life Cycle. There's also a lot of information on application states on the UIApplicationDelegate reference page. Both documents include helpful state transition diagrams and descriptions of what the various states mean.
As a solution; you can use the applicationWillEnterForeground(). It's being called before the applicationDidBecomeActive() and not being triggered by permission request.
Related
I'm writing an iOS application and I'd like to pause my app's motion content when the operating system decides to show a Banner Notification like this one:
Is there a system NSNotification that I can observer or a method that gets called which I can react to? I've triedapplicationWillResignActive, but that isn't called in this case.
I took a stab at it this morning, and I'm inclined to say that there's no public API for this.
I tried using the code outlined here, and didn't catch any notifications. Then, I ran a bunch of "tests" to see if I could find anything.
To test, I created a pair of applications, one to schedule notifications (GitHub link), and one to try and "catch" them (GitHub link). In my Sender app, I can send N notifications every N seconds. I picked some arbitrarily high value and sent them.
In my catcher, I've tried looking at visibleRect values up and down the layer hierarchy. (The keyWindow lives in a layer, but it's superview, and super layer.delegate are both nil) I haven't checked constraints, but that shouldn't matter. I've looked at the application's window, it's nil superview, it's layer, it's subviews. The application's bounds aren't effected either. The app is sandboxed so well, that springboard and notification center don't exist in the app's world.
I started going down the path of accessing private frameworks, but decided it wasn't worth the effort.
I've opened Instruments and looked at the transparency levels of the views. (Is it possible to force all views in a hierarchy to be opaque, and then use that to see if the banner is blocking something? Perhaps it's not "blocking" if it's transparent?)
I've also attempted to take a screenshot, and check the colors in the top area of the screen, but that wouldn't work because you need to pass a view in to the context. Even if it would work, it wouldn't be particularly performant.
Another thought I've had would be to listen for push notifications on the push port, but I doubt that Apple would allow you to catch another app's notifications. As a developer, I wouldn't send private info in an alert, but it's still a concern.
The truth is that notification banners don't really cause your application to become inactive, so I'm not sure that this behavior is wrong. If it's a convenience, file a bug.
How about requesting DeviceWillShowNotificationNotification?
I am building a word game and I want to hide the board when application is suspended?
the code looks fine however it givs a strange behaviour!!,
when I suspend the app nothing will happen but when i resume the application then the board will hide!!
local onSystem = function( event )
if event.type == "applicationSuspend" then
print("suspend")
board_group.alpha = 0
end
end
Runtime:addEventListener( "system", onSystem )
Note: you might wonder how do I know how the application looks when suspended?
the answer is: by pressing the home button twice.
example
SpellTower in normal state
https://dzwonsemrish7.cloudfront.net/items/430k0c0b0y0b413d0b42/Image%202012.11.12%208:08:24%20AM.png?v=4822f549
SpellTower after pressing the home button twice
https://dzwonsemrish7.cloudfront.net/items/280a1y0r2U3W321y1B2z/Image%202012.11.12%208:08:31%20AM.png?v=09c37567
you can see how they are hiding the letters, this is exactly what I want to do for my game, the only difference is i am using Corona SDK
When you do board_group.alpha = 0 you only has set a variable, the result will only take effect after a screen update.
But since the application is suspended... it won't update! So, changing any graphics on applicationSuspend don't work.
I believe the reason is because the application is not considered as suspended. In normal objective c programming it means that applicationWillResignActive is called when the user double clicks on the home button. So what you want to do is to add that code for this part.
Here is a flow of events:
http://www.cocoanetics.com/2010/07/understanding-ios-4-backgrounding-and-delegate-messaging/
Corona seems to have these events:
"applicationStart" occurs when the application is launched and all code
in main.lua is executed.
"applicationExit" occurs when the user quits the application.
"applicationSuspend" occurs when the device needs to suspend the application such as during a phone call or if the phone goes to sleep
from inactivity. In the simulator, this corresponds to the simulator
running in the background. During suspension, no events (not even
enterFrame events) are sent to the application while suspended, so if
you have code that depends on time, you should account for the time
lost to an application being suspended.
"applicationResume" occurs when the application resumes after a suspend. On the phone, this occurs if the application was suspended
because of a phone call. On the simulator, this occurs when the simulator was in the background and now is the foreground application.
So my guess is that you have to implement it outside of the corona API.
According to the corona documents you can implement them in the delegate:
You can intercept UIApplicationDelegate events via your implementation
of the CoronaDelegate protocol.
This protocol conforms to the UIApplicationDelegate protocol. Corona's
internal delegate will call your protocol's method if it is
implemented.
Please keep in mind the following:
Methods that Apple has deprecated will be ignored.
In most cases, your class' version will be invoked after Corona's corresponding version of the UIApplicationDelegate method. There is one situation in which your version will be called before.
In situations where the app is about to suspend or go to the background, your method will be called before Corona's version, e.g.
applicationWillResignActive: and applicationDidEnterBackground:.
http://docs.coronalabs.com/native/enterprise/ios/CoronaDelegate.html
But this is just a guess. Hope it helps!
Edit:
I was thinking, something really simple you could do is catch it outside and present a "pause" screen, then just hide it when the application enters foreground.
So if you can't do that (for now), one other option is to save application state when the application is about to terminate, and then set UIApplicationExitsOnSuspend = true in your plist file. This will cause the application to exit instead of suspending, which will avoid any screenshots, effectively "hiding" the board, etc. The downfall is, the app will have to read the session state when it launches again... this is only useful if your application can be designed to actually exit without losing your state, and is quite honestly, a little extreme. That said, it may be the only way to effectively do what you're trying to do.
Other ideas would be to see if you can add a large black layer to the screen, even though the application is suspending; perhaps this will somehow trigger an internal screen update by natively setting setNeedsDisplay. Also, instead of modifying the alpha, you might consider temporarily removing all of your layers and see if that has a similar effect.
In one of my apps when returning from background I get a non consistent behavior:
Sometimes I get the default.png and sometimes I get a snapshot of the last screen which the app was in.
In both cases it takes the UI a good second or two to respond again.
Therefore I would rather show the default.png rather then "unresponsive UI"
Is there a way to make the app display the default.png always until the app becomes active again?
Currently the "stupid" way to do it I thought about is by displaying some Modal view with the default.png and removing it on return to foreground.
Few Clarification:
I am doing this to avoid unresponsive UI.
I am using the default.png as it looks like loading and gives a better experience then unresponsive UI
The app has to run in background.
(And to whoever asked - no it is not closed when I sometimes return and see the default.png and not the last UI state - App loading from the start has a very different path and I'm sure of that)
Thanks in advance.
This is not a correct behavior and you may experiencing a bug. Basically as long as your app is in the background, when you launch it, you should not see the default.png, unless you remove it from background (double click on home button and delete that app).
For future people interested in this you can use the fact the last view in the app is used to be displayed when the app loads back.
You can display a VC as your moving to background which will represent some loading - hence achieving the desired behavior.
I've already seen a few other apps using the same behavior in cases operations are ran when coming back into the app.
Most probably, you are taking too long (performing too many calculations) in methods such as applicationWillEnterForeground:, applicationDidBecomeActive:, etc. As a simple test, try commenting out the code in these methods and see if the problem occurs again.
Simply set in your Info.plist the property "Application doesn't run in background" to YES. The app will never go in background and when the home button is pressed it will be simply terminated. So you're back to the pre-iOS4 behavior.
Note that when you see now the default image at start-up it is simply because your app has been terminated while it was in background. This is normal especially for apps that take a lot of memory and then don't free it enough before going in the background (I think the threshold for the OS is about 18MB but I'm not sure)
I have an app which requires input when resuming from inactive state (a security view). When resuming from inactive after some time, the UI will freeze for 1-5 seconds before entry can take place on the security view. Following this with Instruments, I see some views have been dealloc'd when memory is needed for other apps. Works as it's supposed to.
The UI freeze appears to happen when lots has been dealloc'd, and the app is reconstituting the dealloc'd views. I'm seeing viewDidLoad's fire etc. Trouble is, the security view has already appeared, giving the user the expectation they can enter their passcode. The app is temporarily unresponsive, which is disconcerting to the user.
I would like to deal with this better, perhaps displaying the security view only when the app is ready for user input.
What's a good way to do that, or is there another suggestion?
Have you included a screenshot of this view as the launch image? It's possible that while the app is loading, it's just showing this screenshot, and giving the impression that the app is frozen, as it won't allow user input on the screenshot.
Is it possible to override the default behavior (close app) of the Home Button? And if how do you do that?
well, there's a reasonable alt to the need to detect if the Home button was tapped. i'm currently working on just such a scenario.
my app allows user input (into UITextViews). a customer has asked for an "autosave" feature where, should they (accidentally) tap the Home button during data entry, could i still capture the data entered and save it.
my testing of the sequence of viewWillDisappear in the view that is collecting the data and applicationWillTerminate show viewWillDisappear getting called before applicationWillTerminate. now i fully appreciate that this is the architected sequence Apple intended, BUT this sequence also precludes setting a simple Boolean in applicationWillTerminate to let the particular viewWillDisappear know that it is disappearing specifically due to applicationWillTerminate.
so the issue still stands. how can a UIView detect that it is disappearing specifically as a result of the app terminating?
Even if it is possible, your app will probably not be approved by Apple.
Are you planning this feature for your own private App or do you want to distribute it later on?
The home button is probably the most critical button on the device on not a good idea to change