A question related to NSUserDefault class - iphone

I'm doing state miantainance code for Iphone os 4.0 using NSUserDefault class.
when i click on home and then click on application then it works but when i click on home and then press on Build and Run button it doesn't work
why is it so?

When you press the home button on iOS 4 the application is not stopped. It is suspended and put into a background state. The state of your application's UI is maintained automatically at this point.
When you hit build an go, the application is forcibly quit before being run again from Xcode.
I assume your code to save the UI state is in the applicationWillTerminate method. If this is the case, then your code will never be run on iOS 4, since this method is no longer called, (at least that's the case I've seen from my own testing and from other people's experiences). And in the case where an app is forcibly quit (ie, by Xcode when hitting build and run), the applicationWillTerminate method is bypassed.
You should, instead, implement the applicationDidEnterBackground and applicationWillEnterForeground methods.
This way, whenever the app is backgrounded, it will write it's state to the NSUserDefaults, ensuring that the state is saved before the app is quit.
On iOS 4 the only way to actually fully quit an app is using the multitasking UI (double pressing the home button) which forcibly quits apps. This is why it's important to implement the backgrounding methods above since they will be much more likely to be executed.
As a last note, it might be worth calling synchronize on the NSUserDefaults instance just after you write your UI state, just to ensure the defaults are written to disk at that time.

Related

In Corona SDK How to hide a group if application suspended?

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.

How can I capture the "Stop" button being pressed in the iOS debugger?

I'm debugging an iOS app, and I need to call some cleanup code in some C++ classes (really, i just want their destructors to be called). When I run the app via XCode with the device attached, and then stop it by pressing the stop button, none of the app delegate methods are called (I'm looking specifically at applicationWillTerminate). However, if I pick up the device and press the home button, it successfully calls both applicationDidEnterBackground and applicationWillResignActive.
What am I doing wrong? I've tried removing all references to any C++ code, effectively making a blank iOS app, and I simply cannot get applicationWillTerminate to be called, or even dealloc in the root view controller. I've even tried using the signal() method along with SIGABRT, SIGKILL, etc., and that does nothing (plus, I can't call the Objective-C methods from a C method anyway). How can I react to the stop button being pressed?
You aren't doing anything wrong, the system just kills your app when you press on the stop button.
There are no methods called because the app is just killed, the same thing can happen when you app is backgrouded and the system needs more memory.
For more precision for the methods called when the app exits / enter in background, check this page
Like #rckoenes said, when you stop the app with the debugger, it kills it.
If your app has the background capability (UIApplicationExitsOnSuspend = NO, it's the default mode), when you quit your app, it is placed in the background instead terminated.

How to know app is about to kill in iOS4.x?

I have an app with locationServices on in background. and have some back ground handle code also.
All I want that when user double click the home button and kill my app I should get notify.There is no application delegate method that is called every time (100%). though the method applicationWillTerminate: according to apple will be called on terminating the app but it is called in very rare cases ( 5 times in 100).
Does any body has some idea about it?
Did you consider implementing applicationDidEnterBackground: method? The doc says that, "In iOS 4.0 and later, this method is called instead of the applicationWillTerminate: method when the user quits an application that supports background execution".
When an app is hidden using the home key, the operating system will suspend it in memory. When this happens, applicationDidEnterBackground: is called. If, at that point, the system decides it needs memory, it will start close apps that are in the background. Sometimes, your app will be on that "hit list". When your app is killed, it is removed from memory completely, just after the pplicationWillTerminate: method is called. The method doesn't get called all the time because sometimes, iOS doesn't need the memory and so it won't actually terminate your app, but rather it will suspend it.
Hey I found a very nice observation, that if your App is running some code in background and user tries to kill it the method applicationWillTerminate is called.

How to Terminate a App on a custom Case. iOS4

My App needs a Internet Connection which is checkt in the ViewDidLoad if there is no Internet connection I want to terminate the app when the Home Button is clickt so that the app start in its initial state next time but only in this case.
If there is a Internet connection from the start the homeButton should bring the app just to the background.
Apple does strongly discourages quitting from application programmatically.
I think you can handle your case without quitting application - when application goes to background(in applicationDidEnterBackground method of application delegate) save some flag indicating that you want to reinit it on resume, then when application comes back to foreground (applicationWillEnterForeground method in delegate) apply your initialization logic in case flag is set.
Programatically terminate an App is a behaviour that will be rejected to be published in the AppStore, as it seems that the application crashed.
If you don't mind that your application will never see the light at the AppStore, you can simply use exit(0).
When your app does not find an internet connection, switch to a view that exactly imitates your Default start-up image, then force that view to stay visible the usual amount of start-up time after any call to making your app active. You can also kill and recreate fresh all your other MVC objects during this time.
That way, no one will know that your app wasn't freshly started when brought back from the background.

How to prevent my app from running in the background on the iPhone

Is there any way to cause an app to quit instead of going to background when the home button is pressed? For security reasons, it would be better if the app did not run in background but actually closed when home is pushed. This is not for users' security, but rather for company data on the app, so it is not a user's choice. I could not find any way to quit other than forcing an exit, which Apple discourages.
See opting out of background execution in the iphone application programming guide:
"If you do not want your application to remain in the background when it is quit, you can explicitly opt out of the background execution model by adding the UIApplicationExitsOnSuspend key to your application’s Info.plist file and setting its value to YES.
When an application opts out, it cycles between the not running, inactive, and active states and never enters the background or suspended states.
When the user taps the Home button to quit the application, the applicationWillTerminate: method of the application delegate is called and the application has approximately five seconds to clean up and exit before it is terminated and moved back to the not running state."
Just go to info.plist of your project and check "Application does not run in background" to YES.
Unfortunately after trying out everything, I was still not able to see my application exiting on pressing home button. It always went into background even though UIApplicationExitsOnSuspend was YES and of type boolean in plist file and I removed the application from Simulator, restarted Xcode and Simulator and tried everything suggested.
Finally I started debugging the application and found one function which was preventing the application from exiting. The function was fairly simple and was downloading some images from network and was getting called from applicationDidFinishLaunching of appDelegate file. This function was delegating the task of creating network connection and downloading data to some other reusable class where I had the below code:
if(isBackgroundProcessingSupported){
appDelegate.bgTask = [app beginBackgroundTaskWithExpirationHandler:^{}];
[NSURLConnection connectionWithRequest:request delegate:self];
}
So finally it turned out that the above code was responsible for putting the application into background on press of home button. When I commented the above code, my application is exiting instead of going into background.
NOTE: The code was there earlier as initially application was supporting background processing.
Hope this helps someone who is also struggling to find the reason like me.