Rework "cancel navigate back" logic.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 08347478a2
commit 25b0f79615

@ -158,7 +158,6 @@ typedef enum : NSUInteger {
OWSVoiceMemoGestureDelegate,
UIDocumentMenuDelegate,
UIDocumentPickerDelegate,
UIGestureRecognizerDelegate,
UIImagePickerControllerDelegate,
UINavigationControllerDelegate,
UITextViewDelegate>
@ -549,10 +548,6 @@ typedef enum : NSUInteger {
// In case we're dismissing a CNContactViewController which requires default system appearance
[UIUtil applySignalAppearence];
// Since we're using a custom back button, we have to do some extra work to manage the
// interactivePopGestureRecognizer
self.navigationController.interactivePopGestureRecognizer.delegate = self;
// We need to recheck on every appearance, since the user may have left the group in the settings VC,
// or on another device.
[self hideInputIfNeeded];
@ -992,10 +987,6 @@ typedef enum : NSUInteger {
self.isViewVisible = NO;
// Since we're using a custom back button, we have to do some extra work to manage the
// interactivePopGestureRecognizer
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
[self.audioAttachmentPlayer stop];
self.audioAttachmentPlayer = nil;

@ -50,6 +50,7 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
@property (nonatomic) NSMutableSet<NSString *> *memberRecipientIds;
@property (nonatomic) BOOL hasUnsavedChanges;
@property (nonatomic) BOOL shouldIgnoreSavedChanges;
@property (nonatomic) BOOL hasAppeared;
@end
@ -551,7 +552,7 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
{
[self.groupNameTextField resignFirstResponder];
if (!self.hasUnsavedChanges) {
if (!self.hasUnsavedChanges || self.shouldIgnoreSavedChanges) {
// If user made no changes, return to conversation settings view.
[self.navigationController popViewControllerAnimated:YES];
return;
@ -570,6 +571,7 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
@"The label for the 'discard' button in alerts and action sheets.")
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *action) {
self.shouldIgnoreSavedChanges = YES;
[self.navigationController popViewControllerAnimated:YES];
}]];
[controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
@ -651,9 +653,13 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
#pragma mark - OWSNavigationView
- (void)navBackButtonPressed
- (BOOL)shouldCancelNavigationBack
{
[self backButtonPressed];
BOOL result = self.hasUnsavedChanges && !self.shouldIgnoreSavedChanges;
if (result) {
[self backButtonPressed];
}
return result;
}
@end

@ -4,9 +4,11 @@
#import <UIKit/UIKit.h>
// Any view controller which wants to be able cancel back button
// presses and back gestures should implement this protocol.
@protocol OWSNavigationView <NSObject>
- (void)navBackButtonPressed;
- (BOOL)shouldCancelNavigationBack;
@end

@ -4,7 +4,15 @@
#import "OWSNavigationController.h"
@interface OWSNavigationController ()
// We use a category to expose UINavigationController's private
// UINavigationBarDelegate methods.
@interface UINavigationController (OWSNavigationController) <UINavigationBarDelegate>
@end
#pragma mark -
@interface OWSNavigationController () <UIGestureRecognizerDelegate>
@end
@ -12,24 +20,53 @@
@implementation OWSNavigationController
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
- (void)viewDidLoad
{
[super viewDidLoad];
self.interactivePopGestureRecognizer.delegate = self;
}
#pragma mark - UINavigationBarDelegate
// All UINavigationController serve as the UINavigationBarDelegate for their navbar.
// We override shouldPopItem: in order to cancel some back button presses - for example,
// if a view has unsaved changes.
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
OWSAssert(self.interactivePopGestureRecognizer.delegate == self);
UIViewController *topViewController = self.topViewController;
BOOL wasBackButtonClicked = topViewController.navigationItem == item;
BOOL wasBackButtonClicked = topViewController.navigationItem == item;
BOOL result = YES;
if (wasBackButtonClicked) {
if ([topViewController respondsToSelector:@selector(navBackButtonPressed)]) {
// if user did press back on the view controller where you handle the navBackButtonPressed
[topViewController performSelector:@selector(navBackButtonPressed)];
return NO;
} else {
// if user did press back but you are not on the view controller that can handle the navBackButtonPressed
[self popViewControllerAnimated:YES];
return YES;
if ([topViewController conformsToProtocol:@protocol(OWSNavigationView)]) {
id<OWSNavigationView> navigationView = (id<OWSNavigationView>)topViewController;
result = ![navigationView shouldCancelNavigationBack];
}
}
// If we're not going to cancel the pop/back, we need to call the super
// implementation since it has important side effects.
if (result) {
result = [super navigationBar:navigationBar shouldPopItem:item];
OWSAssert(result);
}
return result;
}
#pragma mark - UIGestureRecognizerDelegate
// We serve as the UIGestureRecognizerDelegate of the interactivePopGestureRecognizer
// in order to cancel some "back" gestures - for example,
// if a view has unsaved changes.
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
UIViewController *topViewController = self.topViewController;
if ([topViewController conformsToProtocol:@protocol(OWSNavigationView)]) {
id<OWSNavigationView> navigationView = (id<OWSNavigationView>)topViewController;
return ![navigationView shouldCancelNavigationBack];
} else {
// when you call popViewController programmatically you do not want to pop it twice
return YES;
}
}

@ -44,6 +44,8 @@ NSString *const kProfileView_LastPresentedDate = @"kProfileView_LastPresentedDat
@property (nonatomic) BOOL hasUnsavedChanges;
@property (nonatomic) BOOL shouldIgnoreSavedChanges;
@property (nonatomic) ProfileViewMode profileViewMode;
@property (nonatomic) YapDatabaseConnection *databaseConnection;
@ -207,7 +209,7 @@ NSString *const kProfileView_LastPresentedDate = @"kProfileView_LastPresentedDat
{
[self.nameTextField resignFirstResponder];
if (!self.hasUnsavedChanges) {
if (!self.hasUnsavedChanges || self.shouldIgnoreSavedChanges) {
// If user made no changes, return to conversation settings view.
[self profileCompletedOrSkipped];
return;
@ -226,6 +228,7 @@ NSString *const kProfileView_LastPresentedDate = @"kProfileView_LastPresentedDat
@"The label for the 'discard' button in alerts and action sheets.")
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *action) {
self.shouldIgnoreSavedChanges = YES;
[self profileCompletedOrSkipped];
}]];
[controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
@ -495,9 +498,13 @@ NSString *const kProfileView_LastPresentedDate = @"kProfileView_LastPresentedDat
#pragma mark - OWSNavigationView
- (void)navBackButtonPressed
- (BOOL)shouldCancelNavigationBack
{
[self backOrSkipButtonPressed];
BOOL result = self.hasUnsavedChanges && !self.shouldIgnoreSavedChanges;
if (result) {
[self backOrSkipButtonPressed];
}
return result;
}
#pragma mark - Logging

@ -50,6 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) NSMutableSet<NSString *> *memberRecipientIds;
@property (nonatomic) BOOL hasUnsavedChanges;
@property (nonatomic) BOOL shouldIgnoreSavedChanges;
@end
@ -413,7 +414,7 @@ NS_ASSUME_NONNULL_BEGIN
{
[self.groupNameTextField resignFirstResponder];
if (!self.hasUnsavedChanges) {
if (!self.hasUnsavedChanges || self.shouldIgnoreSavedChanges) {
// If user made no changes, return to conversation settings view.
[self.navigationController popViewControllerAnimated:YES];
return;
@ -441,6 +442,7 @@ NS_ASSUME_NONNULL_BEGIN
@"The label for the 'don't save' button in action sheets.")
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *action) {
self.shouldIgnoreSavedChanges = YES;
[self.navigationController popViewControllerAnimated:YES];
}]];
[self presentViewController:controller animated:YES completion:nil];
@ -530,9 +532,13 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - OWSNavigationView
- (void)navBackButtonPressed
- (BOOL)shouldCancelNavigationBack
{
[self backButtonPressed];
BOOL result = self.hasUnsavedChanges && !self.shouldIgnoreSavedChanges;
if (result) {
[self backButtonPressed];
}
return result;
}
@end

Loading…
Cancel
Save