Save the last state of the viewController - ios

I have 2 viewControllers. One of them is for the game screen and it has lots of different variables like labels,buttons,images. The other one is for the pause menu. When i pause the game and tap the resume button, it calls the viewDidLoad of the first viewController naturally.
I want to save the last state of the game when user tap the pause button. Or i want to see the last state of the game when user tap the resume button. I don't want to use nsuserdefault for this,if there is a different solution. Hope i can explain my problem.
Best Regards,
Taha

When i pause the game and tap the resume button, it calls the viewDidLoad of the first viewController naturally
Then you're doing this wrong. There is no reason why the first view controller (with the game screen) should be torn down merely because you are showing the pause menu view controller. You need to rethink your architecture here.
For example, if the first view controller presents the second view controller, then the second view controller's view appears, but the first view controller is not torn down. When the second view controller vanishes again (resume), the first view controller's viewWillAppear: and viewDidAppear: will be called, but not viewDidLoad. Your job is to organize your tasks so that the game pauses on viewWillDisappear: and resumes on viewDidAppear: but the data displayed is not torn down or reset.

Related

Function starts before Storyboard loads

I have a main scene and second scene in my storyboard.
When the app first starts, the main scene viewDidLoad() function is called. Then, I show the second scene. when I go back to first scene viewDidLoad() isn't called.
In the second scene I have implemented the viewDidDisappear() function and it updates a database before the scene disappears.
On the main scene I used viewWillAppear() function to read the same database, but it doesn't work.
Somehow the main scene viewWillAppear is called before the second scene disappear function. It supposed to be other way around isn't it?
Because when you are going back to first page, active story board is disappear and new one is appear.
Can anyone help me to fix this issue?
First, viewDidLoad is only called when the view controller is loaded; when you return to the existing view controller instance, it isn't loaded, the already loaded view controller is simply displayed, so what you see is to be expected.
For your second question, look carefully at the function names;
viewDidDisappear - This function will be called after the view has disappeared as is implied by did
viewWillAppear - This function will be called before the view has appeared as is implied by will
You say "it updates database before the scene disappears.", but by the function name you can see that it will update the database after the view disappears.
You can use the functions viewWillDisappear to update the database as this will be called before the second view controller disappears, and viewDidAppear to update the view after the first view controller has re-appeared.
Alternatively you can use a delegation pattern to allow the second view controller to explicitly tell the first view controller (as its delegate) that the data has changed.

IOS: first tap not working just after loading view

I have noted recently that each of my app view has one particular bug/behaviour: if user taps too fast on a UI component when the view appears, the tap is simply ignored. If the user wait a bit before tapping, the tap works.
Storyboard is used for the storyboard, tap gesture recognisers are on UIImageview and using IOS 10.2.
Through different forums i have read about the following options:
nest the call of "present view controllers" in main thread
Call CFRunLoopWakeup before presentviewcontroller
Add programatically the TapGesturerecognizer
change the states of "delays touches end" and "delays touches began"
disable 3d touch option as similar symptoms was reported to happen in other apps
All above have been unsuccessful.
Anyone would have met similar issues with the first tap just after the view load?
[Update: I realise this misbehaviour is not specific to this app. Two tests to try:
create an xCode Project for iPhone and two view controllers Controller A and Controller B. Two buttons : a button on Controller A view to go to Controller B view and a button Back in Controller B view to go back to Controller A view. Tap to go from View A to B, tap back in B and try immediately to tap on button to go to B. First tap doesn't work either.
Go in Settings of the iPhone. Tap On Notifications. Press On Settings to go back to Main Settings screen, Tap immediately back on Notifications. If fast enough, first tap doesn't work. Second tap works or waiting a bit before first tap.
Question is now: this looks like a common problem across iPhone apps. Would you know if there would be a common setting somewhere? or is this a common bug for given IOS version ?
]
Stephane
This is a general problem (the moment when the view controller is changed, the first tap will be ignored), but this is not a bug that will happen only because the switch view controller's animation has not yet been completed. If you set the animation to false , then the view controller can immediately respond to your click, no matter how fast (anyway faster than your hand) :)

Where to implement auto-save code when using iOS 7 backwards edge swipe?

iOS 7 introduces edge swiping to navigate backwards in a navigation controller (so long as you don't override the leftBarButtonItem, among other things).
Imagine I'm implementing an app similar to Apple Notes. In Apple's app, once the user taps into a note, there is a Back button on the top left, and a Done button on the top right. This view controller is automatically saved after the user navigates away. Even if the user swipes backwards while still editing the note, it will auto-save.
One way to implement this is to write to disk on each key stroke. However, I'm looking for a more efficient implementation.
Which method should I override to perform my auto-save?
To be clear, the auto-save code should be invoked in these three cases:
The user taps the Back button
The user swipes backwards
The user taps the Done button
So far, I've been implementing the save logic in viewWillDisappear, this minimizes the amounts of writes, and also takes care to save if the user kills the app.
Additionally, instead of implementing save logic in the Done button, the Done button can simply call:
[self.navigationController popViewControllerAnimated:YES];
... (e.g. via a delegate, or unwind segue) and it will automatically save as well. All three code paths will go through viewWillDisappear.
Although it could technically be implemented in viewDidDisappear, if the previous view controller needs to display the updated data, this method will be too late.
For more complex view controllers (e.g. those that have destructive behavior once the view controller is dismissed), there are several other things to consider:
Should the save be called if a modal is presented above the current view controller? (e.g. In Apple Notes, imagine that the share button launched a modal; should it save when you tap on this button?). If it is important not to save at this time, you can read the value of presentedViewController. If it has a value, that means viewWillDisappear is being called because a modal is being presented above it.
Should the save be called if a view controller is pushed on to the current navigation stack? (e.g. Again, in Apple Notes, if the share button used a push instead of a modal, should it save?) You can check the value of isMovingFromParentViewController in this case.
If the user taps the home button to quit your app, should it save?
If the user begins swiping backwards then cancels the swipe to stay on the current screen, should it save?
Imagine the view controller is in a modal, when the modal is dismissed should the destructive action happen? Check isBeingDismissed in this case.
Same as above, but imagine the view controller is the second page in a navigation controller than is being presented.

viewDidLoad and viewWillAppear with tab bar controller

I'm looking into the viewDidLoad and viewDidAppear methods to better understand what they both do and I came across an article which uses the example of a banking application to explain how these methods work:
Consider a banking application that shows your current balance. A user
can tap on a button, which presents a list of nearby ATMs in a modal
view controller. In order to get the list of nearby ATMs, the
application must make a core location and web service request.
In this situation, a programmer could get away with requesting the
list of nearby ATMs from the server in viewDidLoad. The view
controller is only presented once, both viewDidLoad and
viewWillAppear: will be called back to back and only once for that
particular view controller instance. The net effect of the code in
either of these two methods will be the same.
But this is a bad idea. Consider what would happen if you wanted to
move the ATM view controller into a tab bar controller. Now, the ATM
view controller – with its ATM fetching code in viewDidLoad only
fetches the list of ATMs once. So you are in Atlanta on Tuesday, open
up your application to look for an ATM, then check your balance. Then
you travel to New York on Wednesday, re-open the banking application,
and you only see ATMs in Atlanta. The view was already loaded, no need
to call viewDidLoad and now you’re looking at stale data.
Sadly, I still don't fully understand how/why both viewDidLoad and viewWillAppear will be called 'back to back', or what adding the ATM view controller to a tab bar controller means in terms of these methods.
viewDidLoad method will call only once a life time of viewController and that is when viewController object will first load in memory.
where as viewWillAppear method will call every time when a view will appear to screen or you can say will be topViewController...
Explanation:
Consider you have tab based app with two tabs. Tab1 associated with viewController1 and tab2 is associated with viewController2. Now when you will run your app and you will see tab one is selected and viewController1 is on view and you want to change to tab2, when you will tap on tab2 then tabVieController2's object will create and load to memory first time hence its viewDidLoad method will call, and soon after that it will appear to window and viewWillAppear will also get call.
Now if you you try changing tabs by click on them only viewWillAppear methods will get called for both, as they are in memory already.
It simple, viewDidLoad get called when the view is load in, either via NIB, storyboard or with the loadView method. The viewWillAppear: is called when the view is presented.
When a view is added to a tab bar it only gets load once, thus the viewDidLoad will only be called once. But if the user switch to an other tab and back to the same view the viewDidLoad will not be called. This is because the view is already loaded.
However the viewWillAppear: is called in both cases just before the view is shown. Thus this will be called when the user first opens the tab and when it switches back to that tab.
I think they are referring to the fact that the view is loaded every time the modal view controller appears (thus the data is constantly refreshed) but only once when it is part of tab bar (only loaded on app launch). Kind of a whacky example to explain the methods though.
You might want to read up on the view controller lifecycle to know when to implement what in which method:
Responding to Display-Related Notifications
View Loading and Unloading

MPMoviePlayerPlaybackDidFinishNotification fires when presenting another view controller

I have created my own MoviePlayerViewController derived from MPMoviePlayerViewController, I present it using the standard presentMoviePlayerViewController method - all works fine. On top of the movie player controller, I present another ShareThisMovie view controller when the user clicks some button (after I pause the movie). I do this using presentViewController.
I don't know why but as soon as the new VC comes up, the underlying MoviePlayerViewController immediately fires MPMoviePlayerPlaybackDidFinishNotification, which I respond to by dismissing the entire VC hierarchy, so the user does not have a chance to interact with the ShareThisMovie controller.
Even if I ignore the notification, still the fact that the movie player fires it means that once the ShareThisMovie controller closes, the movie STARTS OVER FROM THE BEGINNING. This is clearly not what I want...
Why is the MoviePlayerController firing this event? How do I ensure it doesn't, or how to I workaround this? I tried storing the last playback location before showing the ShareThisVideo controller, and setting it back afterwards, but it still plays from the beginning...
tnx
This is happening because when you moving from MoviePlayerViewController to another view controller the MPMoviePlayer stops it playing...so your MPMoviePlayerPlaybackDidFinishNotification Delegate is calling.
you can not continue playing MPMoviePlayer when you are on another ViewController.
one solution is insted of presenting ShareThisMovieviewcontroller, you can simply add UIView for sharing on top of MPMoviePlayer in same controller. this will prevents the MPMoviePlayer to stop.
Not exactly an answer rather than a workaround, but I ended up changing the design: instead of deriving from MPMoviePlayerViewController, I derived from the standard UIViewController, and embedded an MPMoviePlayerController inside it. For some reason, when doing this, the player did not raise a didFinish event when I presented some other VC on top of my player view controller...
Guess my conclusion for now is not to derive a VC from MPMoviePlayerViewController...

Resources