From 08cd2c5dcc0e10ff8a1b60d730b610461fc451ad Mon Sep 17 00:00:00 2001 From: Robert Buskens Date: Wed, 9 Jul 2014 06:51:07 -0500 Subject: [PATCH 1/5] =?UTF-8?q?Basics=20for=20state=20preservation=20/=20r?= =?UTF-8?q?estoration=20setup.=20Not=20complete.=20Workaround=20in=20SWRev?= =?UTF-8?q?ealController,=20toggle=20rearView=20twice=20as=20a=20work=20ar?= =?UTF-8?q?ound.=20The=20state=20of=20the=20menu=20works.=20the=20framewor?= =?UTF-8?q?k=20methods=20are=20getting=20called=20in=20the=20other=20pages?= =?UTF-8?q?,=20but=20haven=E2=80=99t=20debugged=20them.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppDelegate.m | 14 ++++ .../ColorViewController.m | 26 ++++++++ .../MapViewController.m | 23 +++++++ .../MenuViewController.m | 23 +++++++ .../en.lproj/MainStoryboard-iPad.storyboard | 16 ++--- .../SWRevealViewController.m | 65 +++++++++++++++++++ 6 files changed, 159 insertions(+), 8 deletions(-) diff --git a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/AppDelegate.m b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/AppDelegate.m index 849fb72..55dc092 100755 --- a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/AppDelegate.m +++ b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/AppDelegate.m @@ -43,4 +43,18 @@ - (void)applicationWillTerminate:(UIApplication *)application // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } +#pragma mark state preservation / restoration +- (BOOL) application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder { + return YES; +} + +- (BOOL) application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder { + return YES; +} + +- (BOOL) application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + + [self.window makeKeyAndVisible]; + return YES; +} @end diff --git a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/ColorViewController.m b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/ColorViewController.m index 99ba03a..d024cf4 100755 --- a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/ColorViewController.m +++ b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/ColorViewController.m @@ -26,4 +26,30 @@ - (void)viewDidLoad _label.textColor = _color; } +#pragma mark state preservation / restoration +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + NSLog(@"%s", __PRETTY_FUNCTION__); + + // TODO save what you need here + [coder encodeObject: _label.text forKey: @"lableText"]; + + [super encodeRestorableStateWithCoder:coder]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + NSLog(@"%s", __PRETTY_FUNCTION__); + + // TODO restore what you need here + _label.text = [coder decodeObjectForKey: @"labelText"]; + + [super decodeRestorableStateWithCoder:coder]; +} + +- (void)applicationFinishedRestoringState { + NSLog(@"%s", __PRETTY_FUNCTION__); + + // TODO call whatever function you need to visually restore + +} + @end diff --git a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/MapViewController.m b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/MapViewController.m index 482f026..e1bf9c6 100755 --- a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/MapViewController.m +++ b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/MapViewController.m @@ -23,4 +23,27 @@ - (void)viewDidLoad [self.navigationController.navigationBar addGestureRecognizer: self.revealViewController.panGestureRecognizer]; } +#pragma mark state preservation / restoration +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + NSLog(@"%s", __PRETTY_FUNCTION__); + + // TODO save what you need here + + [super encodeRestorableStateWithCoder:coder]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + NSLog(@"%s", __PRETTY_FUNCTION__); + + // TODO restore what you need here + + [super decodeRestorableStateWithCoder:coder]; +} + +- (void)applicationFinishedRestoringState { + NSLog(@"%s", __PRETTY_FUNCTION__); + + // TODO call whatever function you need to visually restore +} + @end diff --git a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/MenuViewController.m b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/MenuViewController.m index c3e0512..072b6a9 100755 --- a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/MenuViewController.m +++ b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/MenuViewController.m @@ -99,4 +99,27 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N return cell; } +#pragma mark state preservation / restoration +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + NSLog(@"%s", __PRETTY_FUNCTION__); + + // TODO save what you need here + + [super encodeRestorableStateWithCoder:coder]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + NSLog(@"%s", __PRETTY_FUNCTION__); + + // TODO restore what you need here + + [super decodeRestorableStateWithCoder:coder]; +} + +- (void)applicationFinishedRestoringState { + NSLog(@"%s", __PRETTY_FUNCTION__); + + // TODO call whatever function you need to visually restore +} + @end diff --git a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/en.lproj/MainStoryboard-iPad.storyboard b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/en.lproj/MainStoryboard-iPad.storyboard index 5e5cfe2..c9deb5f 100755 --- a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/en.lproj/MainStoryboard-iPad.storyboard +++ b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/en.lproj/MainStoryboard-iPad.storyboard @@ -8,7 +8,7 @@ - + @@ -26,8 +26,8 @@ - - + + @@ -117,7 +117,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -162,7 +162,7 @@ - + @@ -189,8 +189,8 @@ - - + + diff --git a/SWRevealViewController/SWRevealViewController.m b/SWRevealViewController/SWRevealViewController.m index 802ccc5..84bc5fc 100755 --- a/SWRevealViewController/SWRevealViewController.m +++ b/SWRevealViewController/SWRevealViewController.m @@ -1643,6 +1643,71 @@ - (void)loadStoryboardControllers } } +#pragma mark state preservation / restoration ++ (UIViewController*) viewControllerWithRestorationIdentifierPath:(NSArray*) identifierComponents coder:(NSCoder*)coder { + NSLog(@"%s", __PRETTY_FUNCTION__); + + SWRevealViewController* vc; + UIStoryboard* sb = [coder decodeObjectForKey:UIStateRestorationViewControllerStoryboardKey]; + + if (sb) { + vc = (SWRevealViewController*)[sb instantiateViewControllerWithIdentifier:@"SWRevealViewController"]; + vc.restorationIdentifier = [identifierComponents lastObject]; + vc.restorationClass = [SWRevealViewController class]; + } + return vc; +} + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + + // this will include the other view controllers in state encoding and decoding + if (_rearViewController) { + [coder encodeObject: _rearViewController forKey: @"rearViewController"]; + } + + if (_frontViewController) { + [coder encodeObject: _frontViewController forKey: @"frontViewController"]; + } + + if (_rightViewController) { + [coder encodeObject: _rightViewController forKey: @"rightViewController"]; + } + + // ??? What's needed to restore what position the views are in + [coder encodeInt: _frontViewPosition forKey: @"frontViewPosition"]; + [coder encodeInt: _rearViewPosition forKey: @"rearViewPosition"]; + [coder encodeInt: _rightViewPosition forKey: @"rightViewPosition"]; + + [super encodeRestorableStateWithCoder:coder]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + + // ??? What's needed to restore what position the views are in + _frontViewPosition = [coder decodeIntForKey: @"frontViewPosition"]; + _rearViewPosition = [coder decodeIntForKey: @"rearViewPosition"]; + _rightViewPosition = [coder decodeIntForKey: @"rightViewPosition"]; + + [super decodeRestorableStateWithCoder:coder]; +} + +- (void)applicationFinishedRestoringState { + + // ??? Get the views to where they should be + + [self _setFrontViewPosition: _frontViewPosition withDuration:0.0]; + + [self revealToggleAnimated: NO]; + [self revealToggleAnimated: NO]; + +// if (_rearViewPosition != FrontViewPositionNone) { +// [self revealToggleAnimated: NO]; +// } +// +// if (_rightViewPosition >= FrontViewPositionLeft) { +// [self rightRevealToggleAnimated: NO]; +// } +} @end From b78fc5f8976eef308196d39810a444bd6e8bfffd Mon Sep 17 00:00:00 2001 From: Robert Buskens Date: Wed, 9 Jul 2014 07:00:01 -0500 Subject: [PATCH 2/5] Push changes to remote --- .../RevealControllerStoryboardExample2/ColorViewController.m | 1 + 1 file changed, 1 insertion(+) diff --git a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/ColorViewController.m b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/ColorViewController.m index d024cf4..0ef9fc1 100755 --- a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/ColorViewController.m +++ b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/ColorViewController.m @@ -48,6 +48,7 @@ - (void)decodeRestorableStateWithCoder:(NSCoder *)coder { - (void)applicationFinishedRestoringState { NSLog(@"%s", __PRETTY_FUNCTION__); + // TODO call whatever function you need to visually restore } From af0eabb2ebfe7fa1b76a9ed19fab0cd4b557e0f1 Mon Sep 17 00:00:00 2001 From: Joan Lluch Date: Wed, 16 Jul 2014 18:41:34 +0200 Subject: [PATCH 3/5] more --- .../SWRevealViewController.h | 127 ++++-- .../SWRevealViewController.m | 377 +++++++++++------- 2 files changed, 326 insertions(+), 178 deletions(-) diff --git a/SWRevealViewController/SWRevealViewController.h b/SWRevealViewController/SWRevealViewController.h index b20d99b..90b7368 100755 --- a/SWRevealViewController/SWRevealViewController.h +++ b/SWRevealViewController/SWRevealViewController.h @@ -28,7 +28,16 @@ RELEASE NOTES - Version 2.1.0 (Current Version) + - New properties 'toggleAnimationType', 'springDampingRatio' + + Version 2.1.1 (Current Version) + + - New property 'frontViewShadowColor' + - New properties 'clipsViewsToBounds' and '_extendedPointInsideHit' + - New delegate methods for finer control of front view location in the overdraw area, as long as deprecation note on former delegate methods + - Other minor changes that should not affect current implementations + + Version 2.1.0 - Removed SWDirectionPanGestureRecognizer. Horizontal panning is filtered on the shouldBegin delegate. This is cleaner, I hope it does not break previous funcionality - Took a cleaner approach to storyboard support. SWRevealViewControllerSegue is now deprecated and you should use SWRevealViewControllerSegueSetController and SWRevealViewControllerSeguePushController instead. @@ -125,7 +134,7 @@ #pragma mark - SWRevealViewController Class // Enum values for setFrontViewPosition:animated: -typedef enum +typedef NS_ENUM( NSInteger, FrontViewPosition) { // Front controller is removed from view. Animated transitioning from this state will cause the same // effect than animating from FrontViewPositionLeftSideMost. Use this instead of FrontViewPositionLeftSideMost when @@ -152,11 +161,20 @@ typedef enum // you intent to remove the front controller view from the view hierarchy. FrontViewPositionRightMostRemoved, -} FrontViewPosition; +}; + +// Enum values for toggleAnimationType +typedef NS_ENUM(NSInteger, SWRevealToggleAnimationType) +{ + SWRevealToggleAnimationTypeSpring, // <- produces a spring based animation + SWRevealToggleAnimationTypeEaseOut, // <- produces a simple ease out curve animation +}; @interface SWRevealViewController : UIViewController +/* Basic API */ + // Object instance init and rear view setting - (id)initWithRearViewController:(UIViewController *)rearViewController frontViewController:(UIViewController *)frontViewController; @@ -176,25 +194,22 @@ typedef enum // presented frontViewController to the right most possition, replacing it, and moving it back to the left position - (void)pushFrontViewController:(UIViewController *)frontViewController animated:(BOOL)animated; -// Front view position, use this to set a particular position state on the controller -// On initialization it is set to FrontViewPositionLeft +// Sets the frontViewController position. You can call the animated version several times with different +// positions to obtain a set of animations that will be performed in order one after the other. @property (nonatomic) FrontViewPosition frontViewPosition; - -// Chained animation of the frontViewController position. You can call it several times in a row to achieve -// any set of animations you wish. Animations will be chained and performed one after the other. - (void)setFrontViewPosition:(FrontViewPosition)frontViewPosition animated:(BOOL)animated; -// Toogles the current state of the front controller between Left or Right and fully visible -// Use setFrontViewPosition to set a particular position -- (void)revealToggleAnimated:(BOOL)animated; -- (void)rightRevealToggleAnimated:(BOOL)animated; // <-- simetric implementation of the above for the rightViewController - // The following methods are meant to be directly connected to the action method of a button // to perform user triggered postion change of the controller views. This is ussually added to a // button on top left or right of the frontViewController - (IBAction)revealToggle:(id)sender; - (IBAction)rightRevealToggle:(id)sender; // <-- simetric implementation of the above for the rightViewController +// Toogles the current state of the front controller between Left or Right and fully visible +// Use setFrontViewPosition to set a particular position +- (void)revealToggleAnimated:(BOOL)animated; +- (void)rightRevealToggleAnimated:(BOOL)animated; // <-- simetric implementation of the above for the rightViewController + // The following method will provide a panGestureRecognizer suitable to be added to any view // in order to perform usual drag and swipe gestures to reveal the rear views. This is usually added to the top bar // of a front controller, but it can be added to your frontViewController view or to the reveal controller view to provide full screen panning. @@ -209,11 +224,12 @@ typedef enum // Thus, you can disable user interactions on your frontViewController view without affecting the tap recognizer. - (UITapGestureRecognizer*)tapGestureRecognizer; -// The following properties are provided for further customization, they are set to default values on initialization, -// you should not generally have to set them +/* The following properties are provided for further customization, they are set to default values on initialization, + you do not generally have to set them */ -// Defines how much of the rear or right view is shown, default is 260. A negative value indicates that the reveal width should be -// computed by substracting the full front view width, so the revealed frontView width is constant. +// Defines how much of the rear or right view is shown, default is 260. +// Negative values indicate that the reveal width should be computed by substracting the full front view width, +// so the revealed frontView width is kept constant when bounds change as opposed to the rear or right width. @property (nonatomic) CGFloat rearViewRevealWidth; @property (nonatomic) CGFloat rightViewRevealWidth; // <-- simetric implementation of the above for the rightViewController @@ -223,7 +239,7 @@ typedef enum // Defines how much displacement is applied to the rear view when animating or dragging the front view, default is 40. @property (nonatomic) CGFloat rearViewRevealDisplacement; -@property (nonatomic) CGFloat rightViewRevealDisplacement; +@property (nonatomic) CGFloat rightViewRevealDisplacement; // <-- simetric implementation of the above for the rightViewController // Defines a width on the border of the view attached to the panGesturRecognizer where the gesture is allowed, // default is 0 which means no restriction. @@ -231,7 +247,7 @@ typedef enum // If YES (the default) the controller will bounce to the Left position when dragging further than 'rearViewRevealWidth' @property (nonatomic) BOOL bounceBackOnOverdraw; -@property (nonatomic) BOOL bounceBackOnLeftOverdraw; +@property (nonatomic) BOOL bounceBackOnLeftOverdraw; // <-- simetric implementation of the above for the rightViewController // If YES (default is NO) the controller will allow permanent dragging up to the rightMostPosition @property (nonatomic) BOOL stableDragOnOverdraw; @@ -239,16 +255,22 @@ typedef enum // If YES (default is NO) the front view controller will be ofsseted vertically by the height of a navigation bar. // Use this on iOS7 when you add an instance of RevealViewController as a child of a UINavigationController (or another SWRevealViewController) -// and you want the front view controller to be presented below the navigation bar of its UINavigationController grand parent . +// and you want the front view controller to be presented below the navigation bar of its UINavigationController grand parent. // The rearViewController will still appear full size and blurred behind the navigation bar of its UINavigationController grand parent @property (nonatomic) BOOL presentFrontViewHierarchically; -// Velocity required for the controller to toggle its state based on a swipe movement, default is 300 +// Velocity required for the controller to toggle its state based on a swipe movement, default is 250 @property (nonatomic) CGFloat quickFlickVelocity; // Duration for the revealToggle animation, default is 0.25 @property (nonatomic) NSTimeInterval toggleAnimationDuration; +// Animation type, default is SWRevealToggleAnimationTypeSpring +@property (nonatomic) SWRevealToggleAnimationType toggleAnimationType; + +// When animation type is SWRevealToggleAnimationTypeSpring determines the damping ratio, default is 1 +@property (nonatomic) CGFloat springDampingRatio; + // Duration for animated replacement of view controllers @property (nonatomic) NSTimeInterval replaceViewAnimationDuration; @@ -258,18 +280,33 @@ typedef enum // Defines the radius of the front view's shadow offset default is {0.0f,2.5f} @property (nonatomic) CGSize frontViewShadowOffset; -//Defines the front view's shadow opacity, default is 1.0f +// Defines the front view's shadow opacity, default is 1.0f @property (nonatomic) CGFloat frontViewShadowOpacity; -// The class properly handles all the relevant calls to appearance methods on the contained controllers. -// Moreover you can assign a delegate to let the class inform you on positions and animation activity. +// Defines the front view's shadow color, default is blackColor +@property (nonatomic) UIColor *frontViewShadowColor; + +// Defines whether the controller should clip subviews to its view bounds. Default is NO. +// Set this to YES when you are presenting this controller as a non full-screen child of a +// custom container controller which does not explicitly clips its subviews. +@property (nonatomic) BOOL clipsViewsToBounds; + +// Defines whether your views clicable area extends beyond the bounds of this controller. Default is NO. +// Set this to YES if you are presenting this controller as a non full-screen child of a custom container and you are not +// clipping your front view to this controller bounds. +@property (nonatomic) BOOL extendsPointInsideHit; + +/* The class properly handles all the relevant calls to appearance methods on the contained controllers. + Moreover you can assign a delegate to let the class inform you on positions and animation activity */ // Delegate @property (nonatomic,weak) id delegate; @end + #pragma mark - SWRevealViewControllerDelegate Protocol + typedef enum { SWRevealControllerOperationReplaceRearController, @@ -296,11 +333,11 @@ typedef enum // Implement this to return NO when you want the tap gesture recognizer to be ignored - (BOOL)revealControllerTapGestureShouldBegin:(SWRevealViewController *)revealController; -// Implement this to return YES if you want this gesture recognizer to share touch events with the pan gesture +// Implement this to return YES if you want other gesture recognizer to share touch events with the pan gesture - (BOOL)revealController:(SWRevealViewController *)revealController panGestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; -// Implement this to return YES if you want this gesture recognizer to share touch events with the tap gesture +// Implement this to return YES if you want other gesture recognizer to share touch events with the tap gesture - (BOOL)revealController:(SWRevealViewController *)revealController tapGestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; @@ -310,11 +347,13 @@ typedef enum // The following methods provide a means to track the evolution of the gesture recognizer. // The 'location' parameter is the X origin coordinate of the front view as the user drags it -// The 'progress' parameter is a positive value from 0 to 1 indicating the front view location relative to the -// rearRevealWidth or rightRevealWidth. 1 is fully revealed, dragging ocurring in the overDraw region will result in values above 1. -- (void)revealController:(SWRevealViewController *)revealController panGestureBeganFromLocation:(CGFloat)location progress:(CGFloat)progress; -- (void)revealController:(SWRevealViewController *)revealController panGestureMovedToLocation:(CGFloat)location progress:(CGFloat)progress; -- (void)revealController:(SWRevealViewController *)revealController panGestureEndedToLocation:(CGFloat)location progress:(CGFloat)progress; +// The 'progress' parameter is a number ranging from 0 to 1 indicating the front view location relative to the +// rearRevealWidth or rightRevealWidth. 1 is fully revealed, dragging ocurring in the overDraw region will result in values above 1. +// The 'overProgress' parameter is a number ranging from 0 to 1 indicating the front view location relative to the +// overdraw region. 0 is fully revealed, 1 is fully overdrawn. Negative values occur inside the normal reveal region +- (void)revealController:(SWRevealViewController *)revealController panGestureBeganFromLocation:(CGFloat)location progress:(CGFloat)progress overProgress:(CGFloat)overProgress; +- (void)revealController:(SWRevealViewController *)revealController panGestureMovedToLocation:(CGFloat)location progress:(CGFloat)progress overProgress:(CGFloat)overProgress; +- (void)revealController:(SWRevealViewController *)revealController panGestureEndedToLocation:(CGFloat)location progress:(CGFloat)progress overProgress:(CGFloat)overProgress; // Notification of child controller replacement - (void)revealController:(SWRevealViewController *)revealController willAddViewController:(UIViewController *)viewController @@ -322,17 +361,21 @@ typedef enum - (void)revealController:(SWRevealViewController *)revealController didAddViewController:(UIViewController *)viewController forOperation:(SWRevealControllerOperation)operation animated:(BOOL)animated; -// Support for custom transition animations while replacing child controllers +// Support for custom transition animations while replacing child controllers. If implemented, it will be fired in response +// to calls to 'setXXViewController' methods - (id)revealController:(SWRevealViewController *)revealController animationControllerForOperation:(SWRevealControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC; - +// DEPRECATED - The following delegate methods will be removed some time in the future +- (void)revealController:(SWRevealViewController *)revealController panGestureBeganFromLocation:(CGFloat)location progress:(CGFloat)progress; // (DEPRECATED) +- (void)revealController:(SWRevealViewController *)revealController panGestureMovedToLocation:(CGFloat)location progress:(CGFloat)progress; // (DEPRECATED) +- (void)revealController:(SWRevealViewController *)revealController panGestureEndedToLocation:(CGFloat)location progress:(CGFloat)progress; // (DEPRECATED) @end #pragma mark - UIViewController(SWRevealViewController) Category -// We add a category of UIViewController to let childViewControllers easily access their parent SWRevealViewController +// A category of UIViewController to let childViewControllers easily access their parent SWRevealViewController @interface UIViewController(SWRevealViewController) - (SWRevealViewController*)revealViewController; @@ -340,29 +383,29 @@ typedef enum @end +#pragma mark - StoryBoard support Classes + +/* StoryBoard support */ + // String identifiers to be applied to segues on a storyboard extern NSString* const SWSegueRearIdentifier; extern NSString* const SWSegueFrontIdentifier; extern NSString* const SWSegueRightIdentifier; +/* This will allow the class to be defined on a storyboard */ -// This will allow the class to be defined on a storyboard -#pragma mark - SWRevealViewControllerSegueSetController Classes - -// Use this along with one of the segue identifiers to segue to the initial state +// Use this along with one of the above segue identifiers to segue to the initial state @interface SWRevealViewControllerSegueSetController : UIStoryboardSegue @end -#pragma mark - SWRevealViewControllerSeguePushController Classes - // Use this to push a view controller @interface SWRevealViewControllerSeguePushController : UIStoryboardSegue @end -#pragma mark - SWRevealViewControllerSegue (Deprecated) +#pragma mark - SWRevealViewControllerSegue (DEPRECATED) @interface SWRevealViewControllerSegue : UIStoryboardSegue // DEPRECATED: USE SWRevealViewControllerSegueSetController instead @property (nonatomic, strong) void(^performBlock)( SWRevealViewControllerSegue* segue, UIViewController* svc, UIViewController* dvc ); -@end \ No newline at end of file +@end diff --git a/SWRevealViewController/SWRevealViewController.m b/SWRevealViewController/SWRevealViewController.m index 802ccc5..35f9f29 100755 --- a/SWRevealViewController/SWRevealViewController.m +++ b/SWRevealViewController/SWRevealViewController.m @@ -25,77 +25,10 @@ Early code inspired on a similar class by Philip Kluz (Philip.Kluz@zuui.org) */ #import -#import #import "SWRevealViewController.h" -//#pragma mark - SWDirectionPanGestureRecognizer -// -//typedef enum -//{ -// SWDirectionPanGestureRecognizerVertical, -// SWDirectionPanGestureRecognizerHorizontal -// -//} SWDirectionPanGestureRecognizerDirection; -// -//@interface SWDirectionPanGestureRecognizer : UIPanGestureRecognizer -// -//@property (nonatomic, assign) SWDirectionPanGestureRecognizerDirection direction; -// -//@end -// -// -//@implementation SWDirectionPanGestureRecognizer -//{ -// BOOL _dragging; -// CGPoint _init; -//} -// -//- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -//{ -// [super touchesBegan:touches withEvent:event]; -// -// UITouch *touch = [touches anyObject]; -// _init = [touch locationInView:self.view]; -// _dragging = NO; -//} -// -// -//- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -//{ -// [super touchesMoved:touches withEvent:event]; -// -// if (self.state == UIGestureRecognizerStateFailed) -// return; -// -// if ( _dragging ) -// return; -// -// const int kDirectionPanThreshold = 5; -// -// UITouch *touch = [touches anyObject]; -// CGPoint nowPoint = [touch locationInView:self.view]; -// -// CGFloat moveX = nowPoint.x - _init.x; -// CGFloat moveY = nowPoint.y - _init.y; -// -// if (abs(moveX) > kDirectionPanThreshold) -// { -// if (_direction == SWDirectionPanGestureRecognizerHorizontal) -// _dragging = YES; -// else -// self.state = UIGestureRecognizerStateFailed; -// } -// else if (abs(moveY) > kDirectionPanThreshold) -// { -// if (_direction == SWDirectionPanGestureRecognizerVertical) -// _dragging = YES ; -// else -// self.state = UIGestureRecognizerStateFailed; -// } -//} -// -//@end + #pragma mark - StatusBar Helper Function @@ -105,10 +38,10 @@ Early code inspired on a similar class by Philip Kluz (Philip.Kluz@zuui.org) static CGFloat statusBarAdjustment( UIView* view ) { CGFloat adjustment = 0.0f; - CGRect viewFrame = [view convertRect:view.bounds toView:nil]; - CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame]; + UIApplication *app = [UIApplication sharedApplication]; + CGRect viewFrame = [view convertRect:view.bounds toView:[app keyWindow]]; + CGRect statusBarFrame = [app statusBarFrame]; - //if ( CGRectContainsRect(viewFrame, statusBarFrame) ) if ( CGRectIntersectsRect(viewFrame, statusBarFrame) ) adjustment = fminf(statusBarFrame.size.width, statusBarFrame.size.height); @@ -162,7 +95,7 @@ - (id)initWithFrame:(CGRect)frame controller:(SWRevealViewController*)controller _frontView = [[UIView alloc] initWithFrame:bounds]; _frontView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; [self reloadShadow]; - + [self addSubview:_frontView]; } return self; @@ -172,7 +105,7 @@ - (id)initWithFrame:(CGRect)frame controller:(SWRevealViewController*)controller - (void)reloadShadow { CALayer *frontViewLayer = _frontView.layer; - frontViewLayer.shadowColor = [UIColor blackColor].CGColor; + frontViewLayer.shadowColor = [_c.frontViewShadowColor CGColor]; frontViewLayer.shadowOpacity = _c.frontViewShadowOpacity; frontViewLayer.shadowOffset = _c.frontViewShadowOffset; frontViewLayer.shadowRadius = _c.frontViewShadowRadius; @@ -193,30 +126,12 @@ - (CGRect)hierarchycalFrameAdjustment:(CGRect)frame } -- (void)layoutSubviews -{ - if ( _disableLayout ) return; - - CGRect bounds = self.bounds; - - CGFloat xLocation = [self frontLocationForPosition:_c.frontViewPosition]; - - [self _layoutRearViewsForLocation:xLocation]; - - CGRect frame = CGRectMake(xLocation, 0.0f, bounds.size.width, bounds.size.height); - _frontView.frame = [self hierarchycalFrameAdjustment:frame]; - - UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:_frontView.bounds]; - _frontView.layer.shadowPath = shadowPath.CGPath; -} - - - (void)prepareRearViewForPosition:(FrontViewPosition)newPosition { if ( _rearView == nil ) { _rearView = [[UIView alloc] initWithFrame:self.bounds]; - _rearView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; + _rearView.autoresizingMask = /*UIViewAutoresizingFlexibleWidth|*/UIViewAutoresizingFlexibleHeight; [self insertSubview:_rearView belowSubview:_frontView]; } @@ -231,7 +146,7 @@ - (void)prepareRightViewForPosition:(FrontViewPosition)newPosition if ( _rightView == nil ) { _rightView = [[UIView alloc] initWithFrame:self.bounds]; - _rightView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; + _rightView.autoresizingMask = /*UIViewAutoresizingFlexibleWidth|*/UIViewAutoresizingFlexibleHeight; [self insertSubview:_rightView belowSubview:_frontView]; } @@ -274,7 +189,84 @@ - (void)dragFrontViewToXLocation:(CGFloat)xLocation } -# pragma mark private +# pragma mark - overrides + +- (void)layoutSubviews +{ + if ( _disableLayout ) return; + + CGRect bounds = self.bounds; + + FrontViewPosition position = _c.frontViewPosition; + CGFloat xLocation = [self frontLocationForPosition:position]; + + // set rear view frames + [self _layoutRearViewsForLocation:xLocation]; + + // set front view frame + CGRect frame = CGRectMake(xLocation, 0.0f, bounds.size.width, bounds.size.height); + _frontView.frame = [self hierarchycalFrameAdjustment:frame]; + + // setup front view shadow path if needed (front view loaded and not removed) + UIViewController *frontViewController = _c.frontViewController; + BOOL viewLoaded = frontViewController != nil && frontViewController.isViewLoaded; + BOOL viewNotRemoved = position > FrontViewPositionLeftSideMostRemoved && position < FrontViewPositionRightMostRemoved; + CGRect shadowBounds = viewLoaded && viewNotRemoved ? _frontView.bounds : CGRectZero; + + UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:shadowBounds]; + _frontView.layer.shadowPath = shadowPath.CGPath; +} + + +- (BOOL)pointInsideD:(CGPoint)point withEvent:(UIEvent *)event +{ + BOOL isInside = [super pointInside:point withEvent:event]; + if ( _c.extendsPointInsideHit ) + { + if ( !isInside && _rearView && [_c.rearViewController isViewLoaded] ) + { + CGPoint pt = [self convertPoint:point toView:_rearView]; + isInside = [_rearView pointInside:pt withEvent:event]; + } + + if ( !isInside && _frontView && [_c.frontViewController isViewLoaded] ) + { + CGPoint pt = [self convertPoint:point toView:_frontView]; + isInside = [_frontView pointInside:pt withEvent:event]; + } + + if ( !isInside && _rightView && [_c.rightViewController isViewLoaded] ) + { + CGPoint pt = [self convertPoint:point toView:_rightView]; + isInside = [_rightView pointInside:pt withEvent:event]; + } + } + return isInside; +} + + +- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event +{ + BOOL isInside = [super pointInside:point withEvent:event]; + if ( !isInside && _c.extendsPointInsideHit ) + { + UIView *testViews[] = { _rearView, _frontView, _rightView }; + UIViewController *testControllers[] = { _c.rearViewController, _c.frontViewController, _c.rightViewController }; + + for ( NSInteger i=0 ; i<3 && !isInside ; i++ ) + { + if ( testViews[i] && [testControllers[i] isViewLoaded] ) + { + CGPoint pt = [self convertPoint:point toView:testViews[i]]; + isInside = [testViews[i] pointInside:pt withEvent:event]; + } + } + } + return isInside; +} + + +# pragma mark - private - (void)_layoutRearViewsForLocation:(CGFloat)xLocation @@ -504,9 +496,66 @@ - (void)animateTransition:(id )transitionC UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; - [UIView transitionFromView:fromViewController.view toView:toViewController.view duration:_duration - options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationOptionOverrideInheritedOptions - completion:^(BOOL finished) { [transitionContext completeTransition:finished]; }]; + if ( fromViewController ) + { + [UIView transitionFromView:fromViewController.view toView:toViewController.view duration:_duration + options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationOptionOverrideInheritedOptions + completion:^(BOOL finished) { [transitionContext completeTransition:finished]; }]; + } + else + { + // tansitionFromView does not correctly handle the case where the fromView is nil (at least on iOS7) it just pops up the toView view with no animation, + // so in such case we replace the crossDissolve animation by a simple alpha animation on the appearing view + UIView *toView = toViewController.view; + CGFloat alpha = toView.alpha; + toView.alpha = 0; + + [UIView animateWithDuration:_duration delay:0 options:UIViewAnimationOptionCurveEaseOut + animations:^{ toView.alpha = alpha;} + completion:^(BOOL finished) { [transitionContext completeTransition:finished];}]; + } +} + +@end + + +#pragma mark - SWRevealViewControllerPanGestureRecognizer + +#import + +@interface SWRevealViewControllerPanGestureRecognizer : UIPanGestureRecognizer +@end + +@implementation SWRevealViewControllerPanGestureRecognizer +{ + BOOL _dragging; + CGPoint _beginPoint; +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesBegan:touches withEvent:event]; + + UITouch *touch = [touches anyObject]; + _beginPoint = [touch locationInView:self.view]; + _dragging = NO; +} + + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesMoved:touches withEvent:event]; + + if ( _dragging || self.state == UIGestureRecognizerStateFailed) + return; + + const int kDirectionPanThreshold = 5; + + UITouch *touch = [touches anyObject]; + CGPoint nowPoint = [touch locationInView:self.view]; + + if (abs(nowPoint.x - _beginPoint.x) > kDirectionPanThreshold) _dragging = YES; + else if (abs(nowPoint.y - _beginPoint.y) > kDirectionPanThreshold) self.state = UIGestureRecognizerStateFailed; } @end @@ -588,14 +637,19 @@ - (void)_initDefaultProperties _stableDragOnLeftOverdraw = NO; _presentFrontViewHierarchically = NO; _quickFlickVelocity = 250.0f; - _toggleAnimationDuration = 0.25; + _toggleAnimationDuration = 0.3; + _toggleAnimationType = SWRevealToggleAnimationTypeSpring; + _springDampingRatio = 1; _replaceViewAnimationDuration = 0.25; _frontViewShadowRadius = 2.5f; _frontViewShadowOffset = CGSizeMake(0.0f, 2.5f); _frontViewShadowOpacity = 1.0f; + _frontViewShadowColor = [UIColor blackColor]; _userInteractionStore = YES; _animationQueue = [NSMutableArray array]; _draggableBorderWidth = 0.0f; + _clipsViewsToBounds = NO; + _extendsPointInsideHit = NO; } @@ -637,7 +691,10 @@ - (void)loadView _contentView = [[SWRevealView alloc] initWithFrame:frame controller:self]; // set the content view to resize along with its superview - [_contentView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; + [_contentView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; + + // set the content view to clip its bounds if requested + [_contentView setClipsToBounds:_clipsViewsToBounds]; // set our contentView to the controllers view self.view = _contentView; @@ -763,21 +820,21 @@ - (void)setRightViewController:(UIViewController *)rightViewController animated: - (void)revealToggleAnimated:(BOOL)animated { - FrontViewPosition toogledFrontViewPosition = FrontViewPositionLeft; + FrontViewPosition toggledFrontViewPosition = FrontViewPositionLeft; if (_frontViewPosition <= FrontViewPositionLeft) - toogledFrontViewPosition = FrontViewPositionRight; + toggledFrontViewPosition = FrontViewPositionRight; - [self setFrontViewPosition:toogledFrontViewPosition animated:animated]; + [self setFrontViewPosition:toggledFrontViewPosition animated:animated]; } - (void)rightRevealToggleAnimated:(BOOL)animated { - FrontViewPosition toogledFrontViewPosition = FrontViewPositionLeft; + FrontViewPosition toggledFrontViewPosition = FrontViewPositionLeft; if (_frontViewPosition >= FrontViewPositionLeft) - toogledFrontViewPosition = FrontViewPositionLeftSide; + toggledFrontViewPosition = FrontViewPositionLeftSide; - [self setFrontViewPosition:toogledFrontViewPosition animated:animated]; + [self setFrontViewPosition:toggledFrontViewPosition animated:animated]; } @@ -822,21 +879,20 @@ - (void)setFrontViewShadowOpacity:(CGFloat)frontViewShadowOpacity } +- (void)setFrontViewShadowColor:(UIColor *)frontViewShadowColor +{ + _frontViewShadowColor = frontViewShadowColor; + [_contentView reloadShadow]; +} + + - (UIPanGestureRecognizer*)panGestureRecognizer { if ( _panGestureRecognizer == nil ) { -// SWDirectionPanGestureRecognizer *panRecognizer = -// [[SWDirectionPanGestureRecognizer alloc] initWithTarget:self action:@selector(_handleRevealGesture:)]; -// -// panRecognizer.direction = SWDirectionPanGestureRecognizerHorizontal; - - UIPanGestureRecognizer *panRecognizer = - [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(_handleRevealGesture:)]; - - panRecognizer.delegate = self; - [_contentView.frontView addGestureRecognizer:panRecognizer]; - _panGestureRecognizer = panRecognizer ; + _panGestureRecognizer = [[SWRevealViewControllerPanGestureRecognizer alloc] initWithTarget:self action:@selector(_handleRevealGesture:)]; + _panGestureRecognizer.delegate = self; + [_contentView.frontView addGestureRecognizer:_panGestureRecognizer]; } return _panGestureRecognizer; } @@ -857,6 +913,14 @@ - (UITapGestureRecognizer*)tapGestureRecognizer } +- (void)setClipsViewsToBounds:(BOOL)clipsViewsToBounds +{ + _clipsViewsToBounds = clipsViewsToBounds; + [_contentView setClipsToBounds:clipsViewsToBounds]; +} + + + #pragma mark - Provided acction methods - (IBAction)revealToggle:(id)sender @@ -897,25 +961,37 @@ - (void)_notifyPanGestureBegan if ( [_delegate respondsToSelector:@selector(revealControllerPanGestureBegan:)] ) [_delegate revealControllerPanGestureBegan:self]; - CGFloat xLocation, dragProgress; - [self _getDragLocation:&xLocation progress:&dragProgress]; - if ( [_delegate respondsToSelector:@selector(revealController:panGestureBeganFromLocation:progress:)] ) + CGFloat xLocation, dragProgress, overProgress; + [self _getDragLocation:&xLocation progress:&dragProgress overdrawProgress:&overProgress]; + + if ( [_delegate respondsToSelector:@selector(revealController:panGestureBeganFromLocation:progress:overProgress:)] ) + [_delegate revealController:self panGestureBeganFromLocation:xLocation progress:dragProgress overProgress:overProgress]; + + else if ( [_delegate respondsToSelector:@selector(revealController:panGestureBeganFromLocation:progress:)] ) [_delegate revealController:self panGestureBeganFromLocation:xLocation progress:dragProgress]; } - (void)_notifyPanGestureMoved { - CGFloat xLocation, dragProgress; - [self _getDragLocation:&xLocation progress:&dragProgress]; - if ( [_delegate respondsToSelector:@selector(revealController:panGestureMovedToLocation:progress:)] ) + CGFloat xLocation, dragProgress, overProgress; + [self _getDragLocation:&xLocation progress:&dragProgress overdrawProgress:&overProgress]; + + if ( [_delegate respondsToSelector:@selector(revealController:panGestureMovedToLocation:progress:overProgress:)] ) + [_delegate revealController:self panGestureMovedToLocation:xLocation progress:dragProgress overProgress:overProgress]; + + else if ( [_delegate respondsToSelector:@selector(revealController:panGestureMovedToLocation:progress:)] ) [_delegate revealController:self panGestureMovedToLocation:xLocation progress:dragProgress]; } - (void)_notifyPanGestureEnded { - CGFloat xLocation, dragProgress; - [self _getDragLocation:&xLocation progress:&dragProgress]; - if ( [_delegate respondsToSelector:@selector(revealController:panGestureEndedToLocation:progress:)] ) + CGFloat xLocation, dragProgress, overProgress; + [self _getDragLocation:&xLocation progress:&dragProgress overdrawProgress:&overProgress]; + + if ( [_delegate respondsToSelector:@selector(revealController:panGestureEndedToLocation:progress:overProgress:)] ) + [_delegate revealController:self panGestureEndedToLocation:xLocation progress:dragProgress overProgress:overProgress]; + + else if ( [_delegate respondsToSelector:@selector(revealController:panGestureEndedToLocation:progress:)] ) [_delegate revealController:self panGestureEndedToLocation:xLocation progress:dragProgress]; if ( [_delegate respondsToSelector:@selector(revealControllerPanGestureEnded:)] ) @@ -944,7 +1020,7 @@ - (void)_getAdjustedFrontViewPosition:(FrontViewPosition*)frontViewPosition forS if ( symetry < 0 ) *frontViewPosition = FrontViewPositionLeft + symetry*(*frontViewPosition-FrontViewPositionLeft); } -- (void)_getDragLocation:(CGFloat*)xLocation progress:(CGFloat*)progress +- (void)_getDragLocationx:(CGFloat*)xLocation progress:(CGFloat*)progress { UIView *frontView = _contentView.frontView; *xLocation = frontView.frame.origin.x; @@ -958,6 +1034,23 @@ - (void)_getDragLocation:(CGFloat*)xLocation progress:(CGFloat*)progress } +- (void)_getDragLocation:(CGFloat*)xLocation progress:(CGFloat*)progress overdrawProgress:(CGFloat*)overProgress +{ + UIView *frontView = _contentView.frontView; + *xLocation = frontView.frame.origin.x; + + int symetry = *xLocation<0 ? -1 : 1; + + CGFloat xWidth = symetry < 0 ? _rightViewRevealWidth : _rearViewRevealWidth; + CGFloat xOverWidth = symetry < 0 ? _rightViewRevealOverdraw : _rearViewRevealOverdraw; + + if ( xWidth < 0 ) xWidth = _contentView.bounds.size.width + xWidth; + + *progress = *xLocation*symetry/xWidth; + *overProgress = (*xLocation*symetry-xWidth)/xOverWidth; +} + + #pragma mark - Deferred block execution queue // Define a convenience macro to enqueue single statements @@ -1012,13 +1105,13 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecogni if ( gestureRecognizer == _panGestureRecognizer ) { if ( [_delegate respondsToSelector:@selector(revealController:panGestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer:)] ) - if ( [_delegate revealController:self panGestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer] == YES ) + if ( [_delegate revealController:self panGestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer] != NO ) return YES; } if ( gestureRecognizer == _tapGestureRecognizer ) { if ( [_delegate respondsToSelector:@selector(revealController:tapGestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer:)] ) - if ( [_delegate revealController:self tapGestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer] == YES ) + if ( [_delegate revealController:self tapGestureRecognizerShouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer] != NO ) return YES; } @@ -1047,8 +1140,9 @@ - (BOOL)_panGestureShouldBegin // forbid gesture if the initial translation is not horizontal UIView *recognizerView = _panGestureRecognizer.view; CGPoint translation = [_panGestureRecognizer translationInView:recognizerView]; - if ( fabs(translation.y/translation.x) > 1 ) - return NO; +// NSLog( @"translation:%@", NSStringFromCGPoint(translation) ); +// if ( fabs(translation.y/translation.x) > 1 ) +// return NO; // forbid gesture if the following delegate is implemented and returns NO if ( [_delegate respondsToSelector:@selector(revealControllerPanGestureShouldBegin:)] ) @@ -1059,12 +1153,16 @@ - (BOOL)_panGestureShouldBegin CGFloat width = recognizerView.bounds.size.width; BOOL draggableBorderAllowing = ( - _frontViewPosition != FrontViewPositionLeft || _draggableBorderWidth == 0.0f || + /*_frontViewPosition != FrontViewPositionLeft ||*/ _draggableBorderWidth == 0.0f || (_rearViewController && xLocation <= _draggableBorderWidth) || (_rightViewController && xLocation >= (width - _draggableBorderWidth)) ); + + + BOOL translationForbidding = ( _frontViewPosition == FrontViewPositionLeft && + ((_rearViewController == nil && translation.x > 0) || (_rightViewController == nil && translation.x < 0)) ); // allow gesture only within the bounds defined by the draggableBorderWidth property - return draggableBorderAllowing ; + return draggableBorderAllowing && !translationForbidding ; } @@ -1321,11 +1419,18 @@ - (void)_setFrontViewPosition:(FrontViewPosition)newPosition withDuration:(NSTim [self _dequeue]; }; - if ( duration > 0.0f ) + if ( duration > 0.0 ) { - [UIView animateWithDuration:duration delay:0.0 - options:UIViewAnimationOptionCurveEaseOut - animations:animations completion:completion]; + if ( _toggleAnimationType == SWRevealToggleAnimationTypeEaseOut ) + { + [UIView animateWithDuration:duration delay:0.0 + options:UIViewAnimationOptionCurveEaseOut animations:animations completion:completion]; + } + else + { + [UIView animateWithDuration:_toggleAnimationDuration delay:0.0 usingSpringWithDamping:_springDampingRatio initialSpringVelocity:1/duration + options:0 animations:animations completion:completion]; + } } else { From ebc5a9572efcb515fff90ab40350aa1c246c7b7b Mon Sep 17 00:00:00 2001 From: Joan Lluch Date: Wed, 16 Jul 2014 23:37:54 +0200 Subject: [PATCH 4/5] state restoration --- .../AppDelegate.m | 13 +- .../ColorViewController.m | 43 ++++-- .../MapViewController.m | 35 +++-- .../en.lproj/MainStoryboard-iPad.storyboard | 2 +- .../en.lproj/MainStoryboard.storyboard | 12 +- .../SWRevealViewController.h | 9 +- .../SWRevealViewController.m | 142 +++++++++++------- 7 files changed, 162 insertions(+), 94 deletions(-) diff --git a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/AppDelegate.m b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/AppDelegate.m index 55dc092..8e06b17 100755 --- a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/AppDelegate.m +++ b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/AppDelegate.m @@ -44,17 +44,20 @@ - (void)applicationWillTerminate:(UIApplication *)application } #pragma mark state preservation / restoration -- (BOOL) application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder { + +- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder +{ return YES; } -- (BOOL) application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder { +- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder +{ return YES; } -- (BOOL) application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - - [self.window makeKeyAndVisible]; +- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + //[self.window makeKeyAndVisible]; return YES; } @end diff --git a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/ColorViewController.m b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/ColorViewController.m index 0ef9fc1..d364a3d 100755 --- a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/ColorViewController.m +++ b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/ColorViewController.m @@ -17,40 +17,57 @@ @implementation ColorViewController - (void)viewDidLoad { [super viewDidLoad]; + [self customSetup]; +} + - [self.revealButtonItem setTarget: self.revealViewController]; - [self.revealButtonItem setAction: @selector( revealToggle: )]; - [self.navigationController.navigationBar addGestureRecognizer: self.revealViewController.panGestureRecognizer]; +- (void)customSetup +{ + SWRevealViewController *revealViewController = self.revealViewController; + if ( revealViewController ) + { + [self.revealButtonItem setTarget: revealViewController]; + [self.revealButtonItem setAction: @selector( revealToggle: )]; + [self.navigationController.navigationBar addGestureRecognizer:revealViewController.panGestureRecognizer]; + } _label.text = _text; _label.textColor = _color; } + #pragma mark state preservation / restoration -- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder +{ NSLog(@"%s", __PRETTY_FUNCTION__); - // TODO save what you need here - [coder encodeObject: _label.text forKey: @"lableText"]; + // Save what you need here + [coder encodeObject: _text forKey: @"text"]; + [coder encodeObject: _color forKey: @"color"]; [super encodeRestorableStateWithCoder:coder]; } -- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder +{ NSLog(@"%s", __PRETTY_FUNCTION__); - // TODO restore what you need here - _label.text = [coder decodeObjectForKey: @"labelText"]; + // Restore what you need here + _color = [coder decodeObjectForKey: @"color"]; + _text = [coder decodeObjectForKey: @"text"]; [super decodeRestorableStateWithCoder:coder]; } -- (void)applicationFinishedRestoringState { + +- (void)applicationFinishedRestoringState +{ NSLog(@"%s", __PRETTY_FUNCTION__); - - // TODO call whatever function you need to visually restore - + // Call whatever function you need to visually restore + [self customSetup]; } @end diff --git a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/MapViewController.m b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/MapViewController.m index e1bf9c6..ba9f855 100755 --- a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/MapViewController.m +++ b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/MapViewController.m @@ -17,33 +17,48 @@ @implementation MapViewController - (void)viewDidLoad { [super viewDidLoad]; - - [self.revealButtonItem setTarget: self.revealViewController]; - [self.revealButtonItem setAction: @selector( revealToggle: )]; - [self.navigationController.navigationBar addGestureRecognizer: self.revealViewController.panGestureRecognizer]; + [self customSetup]; +} + +- (void)customSetup +{ + SWRevealViewController *revealViewController = self.revealViewController; + if ( revealViewController ) + { + [self.revealButtonItem setTarget: self.revealViewController]; + [self.revealButtonItem setAction: @selector( revealToggle: )]; + [self.navigationController.navigationBar addGestureRecognizer: self.revealViewController.panGestureRecognizer]; + } } #pragma mark state preservation / restoration -- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder +{ NSLog(@"%s", __PRETTY_FUNCTION__); - // TODO save what you need here + // Save what you need here [super encodeRestorableStateWithCoder:coder]; } -- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder +{ NSLog(@"%s", __PRETTY_FUNCTION__); - // TODO restore what you need here + // Restore what you need here [super decodeRestorableStateWithCoder:coder]; } -- (void)applicationFinishedRestoringState { + +- (void)applicationFinishedRestoringState +{ NSLog(@"%s", __PRETTY_FUNCTION__); - // TODO call whatever function you need to visually restore + // Call whatever function you need to visually restore + [self customSetup]; } @end diff --git a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/en.lproj/MainStoryboard-iPad.storyboard b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/en.lproj/MainStoryboard-iPad.storyboard index c9deb5f..9f45ecb 100755 --- a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/en.lproj/MainStoryboard-iPad.storyboard +++ b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/en.lproj/MainStoryboard-iPad.storyboard @@ -211,7 +211,7 @@ - + diff --git a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/en.lproj/MainStoryboard.storyboard b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/en.lproj/MainStoryboard.storyboard index aa83630..7224f31 100755 --- a/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/en.lproj/MainStoryboard.storyboard +++ b/RevealControllerStoryboardExample2/RevealControllerStoryboardExample2/en.lproj/MainStoryboard.storyboard @@ -8,7 +8,7 @@ - + @@ -21,7 +21,7 @@ - + @@ -36,7 +36,7 @@ - + @@ -56,7 +56,7 @@ - + @@ -90,7 +90,7 @@ - + @@ -180,7 +180,7 @@ - + diff --git a/SWRevealViewController/SWRevealViewController.h b/SWRevealViewController/SWRevealViewController.h index 90b7368..2d19468 100755 --- a/SWRevealViewController/SWRevealViewController.h +++ b/SWRevealViewController/SWRevealViewController.h @@ -28,7 +28,12 @@ RELEASE NOTES - - New properties 'toggleAnimationType', 'springDampingRatio' + + Version 2.2.0 + + - State restoration support. + - Reverted panGestureRecognizer implementation to before v2.1.0 (works better). + - New properties 'toggleAnimationType', 'springDampingRatio'. Default reveal animation is 'Spring' Version 2.1.1 (Current Version) @@ -167,7 +172,7 @@ typedef NS_ENUM( NSInteger, FrontViewPosition) typedef NS_ENUM(NSInteger, SWRevealToggleAnimationType) { SWRevealToggleAnimationTypeSpring, // <- produces a spring based animation - SWRevealToggleAnimationTypeEaseOut, // <- produces a simple ease out curve animation + SWRevealToggleAnimationTypeEaseOut, // <- produces an ease out curve animation }; diff --git a/SWRevealViewController/SWRevealViewController.m b/SWRevealViewController/SWRevealViewController.m index 9863940..8f3eeb0 100755 --- a/SWRevealViewController/SWRevealViewController.m +++ b/SWRevealViewController/SWRevealViewController.m @@ -29,8 +29,6 @@ Early code inspired on a similar class by Philip Kluz (Philip.Kluz@zuui.org) #import "SWRevealViewController.h" - - #pragma mark - StatusBar Helper Function // computes the required offset adjustment due to the status bar for the passed in view, @@ -678,13 +676,17 @@ - (UIViewController *)childViewControllerForStatusBarHidden - (void)loadView { // Do not call super, to prevent the apis from unfruitful looking for inexistent xibs! + //[super loadView]; + + // load any defined front/rear controllers from the storyboard before + [self loadStoryboardControllers]; - // This is what Apple tells us to set as the initial frame, which is of course totally irrelevant - // with the modern view controller containment patterns, let's leave it for the sake of it! - //CGRect frame = [[UIScreen mainScreen] applicationFrame]; + // This is what Apple used to tell us to set as the initial frame, which is of course totally irrelevant + // with view controller containment patterns, let's leave it for the sake of it! + // CGRect frame = [[UIScreen mainScreen] applicationFrame]; // On iOS7 the applicationFrame does not return the whole screen. This is possibly a bug. - // As a workaround we use the screen bounds, this still works on iOS6 + // As a workaround we use the screen bounds, this still works on iOS6, any zero based frame would work anyway! CGRect frame = [[UIScreen mainScreen] bounds]; // create a custom content view for the controller @@ -699,9 +701,6 @@ - (void)loadView // set our contentView to the controllers view self.view = _contentView; - // load any defined front/rear controllers from the storyboard - [self loadStoryboardControllers]; - // Apple also tells us to do this: _contentView.backgroundColor = [UIColor blackColor]; @@ -1748,14 +1747,16 @@ - (void)loadStoryboardControllers } } + #pragma mark state preservation / restoration -+ (UIViewController*) viewControllerWithRestorationIdentifierPath:(NSArray*) identifierComponents coder:(NSCoder*)coder { - NSLog(@"%s", __PRETTY_FUNCTION__); - - SWRevealViewController* vc; + ++ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder*)coder +{ + SWRevealViewController* vc = nil; UIStoryboard* sb = [coder decodeObjectForKey:UIStateRestorationViewControllerStoryboardKey]; - if (sb) { + if (sb) + { vc = (SWRevealViewController*)[sb instantiateViewControllerWithIdentifier:@"SWRevealViewController"]; vc.restorationIdentifier = [identifierComponents lastObject]; vc.restorationClass = [SWRevealViewController class]; @@ -1763,57 +1764,88 @@ + (UIViewController*) viewControllerWithRestorationIdentifierPath:(NSArray*) ide return vc; } -- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { - // this will include the other view controllers in state encoding and decoding - if (_rearViewController) { - [coder encodeObject: _rearViewController forKey: @"rearViewController"]; - } - - if (_frontViewController) { - [coder encodeObject: _frontViewController forKey: @"frontViewController"]; - } - - if (_rightViewController) { - [coder encodeObject: _rightViewController forKey: @"rightViewController"]; - } - - // ??? What's needed to restore what position the views are in - [coder encodeInt: _frontViewPosition forKey: @"frontViewPosition"]; - [coder encodeInt: _rearViewPosition forKey: @"rearViewPosition"]; - [coder encodeInt: _rightViewPosition forKey: @"rightViewPosition"]; +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder +{ + [coder encodeDouble:_rearViewRevealWidth forKey:@"_rearViewRevealWidth"]; + [coder encodeDouble:_rearViewRevealOverdraw forKey:@"_rearViewRevealOverdraw"]; + [coder encodeDouble:_rearViewRevealDisplacement forKey:@"_rearViewRevealDisplacement"]; + [coder encodeDouble:_rightViewRevealWidth forKey:@"_rightViewRevealWidth"]; + [coder encodeDouble:_rightViewRevealOverdraw forKey:@"_rightViewRevealOverdraw"]; + [coder encodeDouble:_rightViewRevealDisplacement forKey:@"_rightViewRevealDisplacement"]; + [coder encodeBool:_bounceBackOnOverdraw forKey:@"_bounceBackOnOverdraw"]; + [coder encodeBool:_bounceBackOnLeftOverdraw forKey:@"_bounceBackOnLeftOverdraw"]; + [coder encodeBool:_stableDragOnOverdraw forKey:@"_stableDragOnOverdraw"]; + [coder encodeBool:_stableDragOnLeftOverdraw forKey:@"_stableDragOnLeftOverdraw"]; + [coder encodeBool:_presentFrontViewHierarchically forKey:@"_presentFrontViewHierarchically"]; + [coder encodeDouble:_quickFlickVelocity forKey:@"_quickFlickVelocity"]; + [coder encodeDouble:_toggleAnimationDuration forKey:@"_toggleAnimationDuration"]; + [coder encodeInteger:_toggleAnimationType forKey:@"_toggleAnimationType"]; + [coder encodeDouble:_springDampingRatio forKey:@"_springDampingRatio"]; + [coder encodeDouble:_replaceViewAnimationDuration forKey:@"_replaceViewAnimationDuration"]; + [coder encodeDouble:_frontViewShadowRadius forKey:@"_frontViewShadowRadius"]; + [coder encodeCGSize:_frontViewShadowOffset forKey:@"_frontViewShadowOffset"]; + [coder encodeDouble:_frontViewShadowOpacity forKey:@"_frontViewShadowOpacity"]; + [coder encodeObject:_frontViewShadowColor forKey:@"_frontViewShadowColor"]; + [coder encodeBool:_userInteractionStore forKey:@"_userInteractionStore"]; + [coder encodeDouble:_draggableBorderWidth forKey:@"_draggableBorderWidth"]; + [coder encodeBool:_clipsViewsToBounds forKey:@"_clipsViewsToBounds"]; + [coder encodeBool:_extendsPointInsideHit forKey:@"_extendsPointInsideHit"]; + + [coder encodeObject:_rearViewController forKey:@"_rearViewController"]; + [coder encodeObject:_frontViewController forKey:@"_frontViewController"]; + [coder encodeObject:_rightViewController forKey:@"_rightViewController"]; + + [coder encodeInteger:_frontViewPosition forKey:@"_frontViewPosition"]; [super encodeRestorableStateWithCoder:coder]; } -- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder +{ + _rearViewRevealWidth = [coder decodeDoubleForKey:@"_rearViewRevealWidth"]; + _rearViewRevealOverdraw = [coder decodeDoubleForKey:@"_rearViewRevealOverdraw"]; + _rearViewRevealDisplacement = [coder decodeDoubleForKey:@"_rearViewRevealDisplacement"]; + _rightViewRevealWidth = [coder decodeDoubleForKey:@"_rightViewRevealWidth"]; + _rightViewRevealOverdraw = [coder decodeDoubleForKey:@"_rightViewRevealOverdraw"]; + _rightViewRevealDisplacement = [coder decodeDoubleForKey:@"_rightViewRevealDisplacement"]; + _bounceBackOnOverdraw = [coder decodeBoolForKey:@"_bounceBackOnOverdraw"]; + _bounceBackOnLeftOverdraw = [coder decodeBoolForKey:@"_bounceBackOnLeftOverdraw"]; + _stableDragOnOverdraw = [coder decodeBoolForKey:@"_stableDragOnOverdraw"]; + _stableDragOnLeftOverdraw = [coder decodeBoolForKey:@"_stableDragOnLeftOverdraw"]; + _presentFrontViewHierarchically = [coder decodeBoolForKey:@"_presentFrontViewHierarchically"]; + _quickFlickVelocity = [coder decodeDoubleForKey:@"_quickFlickVelocity"]; + _toggleAnimationDuration = [coder decodeDoubleForKey:@"_toggleAnimationDuration"]; + _toggleAnimationType = [coder decodeIntegerForKey:@"_toggleAnimationType"]; + _springDampingRatio = [coder decodeDoubleForKey:@"_springDampingRatio"]; + _replaceViewAnimationDuration = [coder decodeDoubleForKey:@"_replaceViewAnimationDuration"]; + _frontViewShadowRadius = [coder decodeDoubleForKey:@"_frontViewShadowRadius"]; + _frontViewShadowOffset = [coder decodeCGSizeForKey:@"_frontViewShadowOffset"]; + _frontViewShadowOpacity = [coder decodeDoubleForKey:@"_frontViewShadowOpacity"]; + _frontViewShadowColor = [coder decodeObjectForKey:@"_frontViewShadowColor"]; + _userInteractionStore = [coder decodeBoolForKey:@"_userInteractionStore"]; + _animationQueue = [NSMutableArray array]; + _draggableBorderWidth = [coder decodeDoubleForKey:@"_draggableBorderWidth"]; + _clipsViewsToBounds = [coder decodeBoolForKey:@"_clipsViewsToBounds"]; + _extendsPointInsideHit = [coder decodeBoolForKey:@"_extendsPointInsideHit"]; + + [self setRearViewController:[coder decodeObjectForKey:@"_rearViewController"]]; + [self setFrontViewController:[coder decodeObjectForKey:@"_frontViewController"]]; + [self setRightViewController:[coder decodeObjectForKey:@"_rightViewController"]]; - // ??? What's needed to restore what position the views are in - _frontViewPosition = [coder decodeIntForKey: @"frontViewPosition"]; - _rearViewPosition = [coder decodeIntForKey: @"rearViewPosition"]; - _rightViewPosition = [coder decodeIntForKey: @"rightViewPosition"]; + [self setFrontViewPosition:[coder decodeIntForKey: @"_frontViewPosition"]]; [super decodeRestorableStateWithCoder:coder]; } -- (void)applicationFinishedRestoringState { - // ??? Get the views to where they should be - - [self _setFrontViewPosition: _frontViewPosition withDuration:0.0]; - - [self revealToggleAnimated: NO]; - [self revealToggleAnimated: NO]; - -// if (_rearViewPosition != FrontViewPositionNone) { -// [self revealToggleAnimated: NO]; -// } -// -// if (_rightViewPosition >= FrontViewPositionLeft) { -// [self rightRevealToggleAnimated: NO]; -// } +- (void)applicationFinishedRestoringState +{ + // nothing to do at this stage } + @end @@ -1825,11 +1857,7 @@ - (SWRevealViewController*)revealViewController { UIViewController *parent = self; Class revealClass = [SWRevealViewController class]; - - while ( nil != (parent = [parent parentViewController]) && ![parent isKindOfClass:revealClass] ) - { - } - + while ( nil != (parent = [parent parentViewController]) && ![parent isKindOfClass:revealClass] ) {} return (id)parent; } From ce08628d412556a5de5ebfdb33e7026733596333 Mon Sep 17 00:00:00 2001 From: Joan Lluch Date: Wed, 16 Jul 2014 23:42:16 +0200 Subject: [PATCH 5/5] v2.2.0 --- SWRevealViewController.podspec | 2 +- SWRevealViewController/SWRevealViewController.h | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/SWRevealViewController.podspec b/SWRevealViewController.podspec index 9258e43..500afae 100644 --- a/SWRevealViewController.podspec +++ b/SWRevealViewController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "SWRevealViewController" - s.version = "2.1.0" + s.version = "2.2.0" s.summary = "A UIViewController subclass for presenting two view controllers inspired in the Facebook app, done right." s.homepage = "https://github.com/John-Lluch/SWRevealViewController" s.license = "MIT" diff --git a/SWRevealViewController/SWRevealViewController.h b/SWRevealViewController/SWRevealViewController.h index 2d19468..1cf4ffb 100755 --- a/SWRevealViewController/SWRevealViewController.h +++ b/SWRevealViewController/SWRevealViewController.h @@ -29,14 +29,11 @@ RELEASE NOTES - Version 2.2.0 + Version 2.2.0 (Current Version) - - State restoration support. + - State Restoration support. - Reverted panGestureRecognizer implementation to before v2.1.0 (works better). - New properties 'toggleAnimationType', 'springDampingRatio'. Default reveal animation is 'Spring' - - Version 2.1.1 (Current Version) - - New property 'frontViewShadowColor' - New properties 'clipsViewsToBounds' and '_extendedPointInsideHit' - New delegate methods for finer control of front view location in the overdraw area, as long as deprecation note on former delegate methods