I'm trying to add some finer control to the Storyboard controller and I hit a blockage with the back button.
I have a basic Storyboard with push transition. I want to be able to catch when the user presses on the back button (the one generated automatically) and decid if I want the view to go back or not.
The scenario is to show a message to the user asking if he wants to go back warning him that he is going to lose his work if he does,
Sounds simple, yet I can't find how to do it.
Any ideas
You don't get any sort of message by default when the back button is pressed. If you want to provide this sort of functionality, you have two options:
1) Provide a custom back button and set it as the leftNavigationItem of your UIViewController's navigation bar
2) Subclass UINavigationController and override a method such as popToRootViewController:animated:
Try using UIAlertView Delegate.
In your buttonPressed Action, provide an alert view with message with two buttons YES and NO.
define button at index action for YES and NO -ie- YES: dismiss current view and NO: remain on current view.
Search Apple Docs on alert view delegate
Related
Is there a way to prevent the user from dismissing a modal controller?
I think it is pretty common to want to "block" the main Watch App interface while asking the user to open the iPhone counterpart or to perform some action there.
My current solution is to present again the controller when it gets dismissed but its clunky.
There's a somewhat kludgy way to get around this issue using reloadRootControllers. When you call reloadRootControllers(withNamesAndContexts:) with the name of a WKInterfaceController that you've named in your storyboard, it has a similar effect to presenting that controller modally. However, since it's now the root controller, it doesn't have a cancel button. I don't really like this, but it does get the job done.
Note this method is deprecated since watchOS 4.
Apple Documentation on reloadRootControllers(withNamesAndContexts:)
The trick is to make the modal screen fullscreen and change the inset top value for your main group.
You can't prevent a modal interface controller from being dismissed, as the system automatically dismisses it when the title is tapped.
Since your code isn't asked if it should happen, but only knows that it is happening, there's no way to intercept or cancel that action. The WKInterfaceController documentation briefly touches on this.
When the user taps the title string, WatchKit automatically dismisses the modal interface without taking any further actions.
What can you do?
While you don't know when the Cancel title is tapped, there is a hack which "hides" the Cancel title.
This may confuse users who might wonder how to dismiss the modal, or mislead others into thinking the modal couldn't be dismissed.
What does the HIG recommend?
Circumventing a Human Interface Guideline would likely degrade the entire user experience.
The top-left corner of the modal sheet is reserved for the Close button, which dismisses the interface.
Some users might be frustrated or annoyed if
there is no apparent way to cancel, or
the modal presents itself again after repeatedly being cancelled.
Since the user expects to be able to dismiss the modal, perhaps you could allow them to do just that, then simply display some form of reminder in the presenting interface controller (to log in, or enable permissions).
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.
Is there any way to know when the cancel/dismiss button is tapped on the Apple Watch?
- (void)didDeactivate
Is not an option because that is called whenever the watch goes dark. I'm trying to sync data with the parent iPhone app and this makes it tough to cancel an operation on the parent app.
While you can't get the cancel directly, you can tell which view controller is active (because your code displayed it) and then tell when they switch. So you can set some flags on display and on de-activate, to tell when the view controller with the cancel button goes away.
Think of it another way, if your view controller disappears and another one displays, the activate of the other controller tells you the watch did not sleep.
Unfortunately, the current version of WatchKit has no method to determine if the Cancel button is tapped. The closest you'll get is the didDeactivate event that you've already mentioned.
I have a One main view controller and in that I am having two sub view controllers named like rightViewcontroller and leftViewcontroller. When we press the menu items from the right view then I am changing the left view controller.That's working fine.Here my problem is If I get any alert that's only fixed to any of the View controller's.Then user able to press the other view which is not having the alert(those are custom alert's. I need custom alerts as per the client requirement)in iPad. Please Help me
Thank's in advance
When you get an alert on, say, the leftViewController, then disable the user interaction on the other viewControllers.
something like:
rightViewController.view.userInteractionEnabled = NO;
It seems when you present your alert you are showing it over one of the views like showInView:self.view when in fact you should show it over the parent view so it covers both like showInView:self.navigationController.parentViewController.view (that's just pseudo code).
Without seeing your code you use to present it currently I can't give you exact code.
Another way would be to first get a pointer to the parent view controller or navigation controller and show it there.
I have a table view that pushes to a detail view controller. From the detail view controller, when I press the 'back' button, I'd like an integer value to change. How do I edit the navigation bar back button's action programatically. The back button is automatically placed in my app because I'm using a table view so I didn't actually create the button, so I don't know how to affect it's method.
To be clear, I still want the back button to go back to the original view, but simultaneously change an integer's value. Thanks!
Thanks PengOne to point me to this direction.
Add the UINavigationBarDelegate in the header file and use this in the .m file:
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
//insert your back button handling logic here
// let the pop happen
return YES;
}
I've figured out an easy fix to this. I simply unchecked 'Shows Navigation Bar' in the Interface Builder for the UINavigationController that the Table View was contained in. Then I used a UINavigationBar to replicate the look (but be able to add and delete buttons as I pleased).
After that I just created IBAction's that I connected to the buttons and could control an integer value from there.
(P.S. The only problem with this is that there is no 'Back' button left pointing arrow shape in the XCode interface builder as many of you know. There are solutions around this that are pretty easily found if you search).
If you're using a UINavigationController, then UINavigationBarDelegate is the delegate class and it implements -navigationBar:shouldPopItem. You can put the action you want to trigger in that method, e.g. incrementing or decrementing a counter.
You could try implementing viewDidDisappear, which should be called as the detail view controller's view goes out of view.