Commits

José Manuel Sánchez Peñarroja committed 9a9cb38

Refactored progress views. Added easing functions for progress. Now we don’t allow progress to go back

Comments (0)

Files changed (14)

   s.dependency 'Base64', '~> 1.0.1'
   
 	s.subspec "Core" do |core|
-		# core.source_files = 'bmf/shared/*.{h,m}'
-    
-    # core.ios.source_files = 'bmf/ios/*.{h,m}'
-    
-#     core.osx.source_files = 'bmf/mac/*.{h,m}'
-# core.exclude_files = 'bmf/shared/subspecs/**/*.{h,m}'
-#   core.exclude_files = 'bmf/shared/subspecs/**/*.{h,m}'
-# core.ios.exclude_files = 'bmf/ios/subspecs/**/*.{h,m}'
-# core.osx.exclude_files = 'bmf/mac/subspecs/**/*.{h,m}'
 
     core.resources = 'bmf/**/*.{xib}'
     core.resource_bundle = { 'BMF' => 'bmf/**/*.{lproj,png,jpg}' }
     end
     
     core.subspec "Data" do |s|
-      s.source_files = 'bmf/shared/data/*.{h,m}'
+      s.source_files = 'bmf/shared/data/**/*.{h,m}'
 
       s.subspec "Data Sources" do |s|
         s.source_files = 'bmf/shared/data/data sources/**/*.{h,m}'
     end
     
     core.subspec "Views" do |s|
-      s.ios.source_files = 'bmf/ios/views/*.{h,m}'
+      s.ios.source_files = 'bmf/ios/views/**/*.{h,m}'
+      s.source_files = 'bmf/shared/views/**/*.{h,m}'
       
       core.subspec "Cell configuration" do |s|
-        s.ios.source_files = 'bmf/ios/views/cell configuration/*.{h,m}'
+        s.ios.source_files = 'bmf/ios/views/cell configuration/**/*.{h,m}'
       end
 
       core.subspec "Cell factory" do |s|
-        s.ios.source_files = 'bmf/ios/views/cell factory/*.{h,m}'
+        s.ios.source_files = 'bmf/ios/views/cell factory/**/*.{h,m}'
       end
       
       core.subspec "Cells" do |s|
-        s.ios.source_files = 'bmf/ios/views/cells/*.{h,m}'
+        s.ios.source_files = 'bmf/ios/views/cells/**/*.{h,m}'
       end
       
       core.subspec "View register" do |s|
-        s.ios.source_files = 'bmf/ios/views/view register/*.{h,m}'
+        s.ios.source_files = 'bmf/ios/views/view register/**/*.{h,m}'
       end
     end
 	end

Example/Example.xcworkspace/xcuserdata/josanchez.xcuserdatad/UserInterfaceState.xcuserstate

Binary file modified.

bmf/ios/behaviors/BMFItemTapPresentsViewControllerBehavior.h

+//
+//  BMFPresentViewControllerBehavior.h
+//  Pods
+//
+//  Created by Jose Manuel Sánchez Peñarroja on 23/05/14.
+//
+//
+
+#import "BMFItemTapBehavior.h"
+
+#import "BMFObjectControllerProtocol.h"
+
+typedef NS_ENUM(NSInteger, BMFPresentViewControllerBehaviorMode) {
+    BMFPresentViewControllerBehaviorAutomatic,
+    BMFPresentViewControllerBehaviorSegue,
+	BMFPresentViewControllerBehaviorModal,
+	BMFPresentViewControllerBehaviorPush
+};
+
+@interface BMFItemTapPresentsViewControllerBehavior : BMFItemTapBehavior
+
+@property (nonatomic, assign) BMFPresentViewControllerBehaviorMode mode;
+
+/// Identifier of the segue to be performed
+@property (nonatomic, strong) NSString *segueIdentifier;
+
+/// View controller to be pushed or presented
+@property (nonatomic, strong) UIViewController<BMFObjectControllerProtocol> *detailViewController;
+
+/// YES by default
+@property (nonatomic, assign) BOOL animated;
+
+
+@end

bmf/ios/behaviors/BMFItemTapPresentsViewControllerBehavior.m

+//
+//  BMFPresentViewControllerBehavior.m
+//  Pods
+//
+//  Created by Jose Manuel Sánchez Peñarroja on 23/05/14.
+//
+//
+
+#import "BMFItemTapPresentsViewControllerBehavior.h"
+
+#import "BMFTypes.h"
+
+#import "BMFObjectControllerProtocol.h"
+#import "BMFViewController.h"
+
+@implementation BMFItemTapPresentsViewControllerBehavior
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        _animated = YES;
+    }
+    return self;
+}
+
+- (void) itemTapped:(id) item {
+
+	BMFAssertReturn(self.object);
+
+	BMFPresentViewControllerBehaviorMode currentMode = self.mode;
+	
+	if (self.mode==BMFPresentViewControllerBehaviorAutomatic) {
+		if (self.segueIdentifier.length>0) currentMode = BMFPresentViewControllerBehaviorSegue;
+		else if (self.object.navigationController) currentMode = BMFPresentViewControllerBehaviorPush;
+		else currentMode = BMFPresentViewControllerBehaviorModal;
+	}
+
+	
+	if (currentMode==BMFPresentViewControllerBehaviorSegue) {
+		BMFAssertReturn(self.segueIdentifier.length>0);
+
+		BMFViewController *vc = [BMFViewController BMF_cast:self.object];
+		BMFAssertReturn(vc);
+		[vc performSegueWithIdentifier:self.segueIdentifier prepareBlock:^(UIStoryboardSegue *segue) {
+			UIViewController *detailVC = segue.destinationViewController;
+			BMFAssertReturn([detailVC conformsToProtocol:@protocol(BMFObjectControllerProtocol)]);
+			
+			id<BMFObjectControllerProtocol> destinationVC = detailVC;
+			destinationVC.objectStore.object = item;
+		}];
+	}
+	else if (currentMode==BMFPresentViewControllerBehaviorModal) {
+		BMFAssertReturn(self.detailViewController);
+		
+		self.detailViewController.objectStore.object = item;
+		
+		[self.object presentViewController:self.detailViewController animated:self.animated completion:nil];
+	}
+	else if (currentMode==BMFPresentViewControllerBehaviorPush) {
+		BMFAssertReturn(self.detailViewController);
+
+		self.detailViewController.objectStore.object = item;
+		[self.object.navigationController pushViewController:self.detailViewController animated:self.animated];
+	}
+	else {
+		[NSException raise:@"Unknown format for present view controller" format:@"%@",self];
+	}
+}
+
+
+@end

bmf/ios/behaviors/BMFPresentViewControllerBehavior.h

-//
-//  BMFPresentViewControllerBehavior.h
-//  Pods
-//
-//  Created by Jose Manuel Sánchez Peñarroja on 23/05/14.
-//
-//
-
-#import "BMFItemTapBehavior.h"
-
-#import "BMFObjectControllerProtocol.h"
-
-typedef NS_ENUM(NSInteger, BMFPresentViewControllerBehaviorMode) {
-    BMFPresentViewControllerBehaviorAutomatic,
-    BMFPresentViewControllerBehaviorSegue,
-	BMFPresentViewControllerBehaviorModal,
-	BMFPresentViewControllerBehaviorPush
-};
-
-@interface BMFPresentViewControllerBehavior : BMFItemTapBehavior
-
-@property (nonatomic, assign) BMFPresentViewControllerBehaviorMode mode;
-
-/// Identifier of the segue to be performed
-@property (nonatomic, strong) NSString *segueIdentifier;
-
-/// View controller to be pushed or presented
-@property (nonatomic, strong) UIViewController<BMFObjectControllerProtocol> *detailViewController;
-
-/// YES by default
-@property (nonatomic, assign) BOOL animated;
-
-
-@end

bmf/ios/behaviors/BMFPresentViewControllerBehavior.m

-//
-//  BMFPresentViewControllerBehavior.m
-//  Pods
-//
-//  Created by Jose Manuel Sánchez Peñarroja on 23/05/14.
-//
-//
-
-#import "BMFPresentViewControllerBehavior.h"
-
-#import "BMFTypes.h"
-
-#import "BMFObjectControllerProtocol.h"
-#import "BMFViewController.h"
-
-@implementation BMFPresentViewControllerBehavior
-
-- (instancetype)init
-{
-    self = [super init];
-    if (self) {
-        _animated = YES;
-    }
-    return self;
-}
-
-- (void) itemTapped:(id) item {
-
-	BMFAssertReturn(self.object);
-
-	BMFPresentViewControllerBehaviorMode currentMode = self.mode;
-	
-	if (self.mode==BMFPresentViewControllerBehaviorAutomatic) {
-		if (self.segueIdentifier.length>0) currentMode = BMFPresentViewControllerBehaviorSegue;
-		else if (self.object.navigationController) currentMode = BMFPresentViewControllerBehaviorPush;
-		else currentMode = BMFPresentViewControllerBehaviorModal;
-	}
-
-	
-	if (currentMode==BMFPresentViewControllerBehaviorSegue) {
-		BMFAssertReturn(self.segueIdentifier.length>0);
-
-		BMFViewController *vc = [BMFViewController BMF_cast:self.object];
-		BMFAssertReturn(vc);
-		[vc performSegueWithIdentifier:self.segueIdentifier prepareBlock:^(UIStoryboardSegue *segue) {
-			UIViewController *detailVC = segue.destinationViewController;
-			BMFAssertReturn([detailVC conformsToProtocol:@protocol(BMFObjectControllerProtocol)]);
-			
-			id<BMFObjectControllerProtocol> destinationVC = detailVC;
-			destinationVC.objectStore.object = item;
-		}];
-	}
-	else if (currentMode==BMFPresentViewControllerBehaviorModal) {
-		BMFAssertReturn(self.detailViewController);
-		
-		self.detailViewController.objectStore.object = item;
-		
-		[self.object presentViewController:self.detailViewController animated:self.animated completion:nil];
-	}
-	else if (currentMode==BMFPresentViewControllerBehaviorPush) {
-		BMFAssertReturn(self.detailViewController);
-
-		self.detailViewController.objectStore.object = item;
-		[self.object.navigationController pushViewController:self.detailViewController animated:self.animated];
-	}
-	else {
-		[NSException raise:@"Unknown format for present view controller" format:@"%@",self];
-	}
-}
-
-
-@end

bmf/ios/subspecs/m13/BMFM13NavigationBarProgressView.h

 
 #import <Foundation/Foundation.h>
 
-#import "BMFLoaderViewProtocol.h"
+#import "BMFProgressUI.h"
 
-@interface BMFM13NavigationBarProgressView : NSObject <BMFLoaderViewProtocol>
-
-@property (nonatomic, strong) NSString *message;
-
-@property (nonatomic, strong) BMFProgress *progress;
-
-@property (nonatomic, copy) BMFActionBlock reloadActionBlock;
+@interface BMFM13NavigationBarProgressView : BMFProgressUI
 
 @end

bmf/ios/subspecs/m13/BMFM13NavigationBarProgressView.m

 
 @implementation BMFM13NavigationBarProgressView
 
-- (instancetype)init
-{
-    self = [super init];
-    if (self) {
-		
-		_progress = [BMFProgress new];
+- (void) addToViewController:(UIViewController *) vc {
+	self.viewController = vc;
+}
+
+- (void) updateRunning: (BOOL) running {
+	if (running) {
+		DDLogDebug(@"Fraction completed when starting: %f",self.progress.fractionCompleted);
 		
-        @weakify(self);
-		[[RACObserve(self, progress.running) deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNumber *runningNumber) {
-			@strongify(self);
-			
-			if (runningNumber.boolValue) {
-				DDLogDebug(@"Fraction completed when starting: %f",self.progress.fractionCompleted);
-				
-				[self.viewController.navigationController setProgress:0 animated:NO];
-				[self.viewController.navigationController showProgress];
+		[self.viewController.navigationController setProgress:0 animated:NO];
+		[self.viewController.navigationController showProgress];
+	}
+	else {
+		if (self.progress.fractionCompleted==1) {
+			if (self.progress.failedError) {
+				if (self.viewController.navigationController.isShowingProgressBar) {
+					[self.viewController.navigationController cancelProgress];
+				}
 			}
 			else {
-				if (self.progress.fractionCompleted==1) {
-					if (self.progress.failedError) {
-						if (self.viewController.navigationController.isShowingProgressBar) {
-							[self.viewController.navigationController cancelProgress];	
-						}
-					}
-					else {
-						if (self.viewController.navigationController.isShowingProgressBar) {
-							[self.viewController.navigationController finishProgress];
-						}
-					}
+				if (self.viewController.navigationController.isShowingProgressBar) {
+					[self.viewController.navigationController finishProgress];
 				}
 			}
-
-		}];
-		[[RACObserve(self, progress.fractionCompleted) deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNumber *completed) {
-			@strongify(self);
-			DDLogInfo(@"Progress: %f",completed.floatValue);
-			if (self.progress.running) [self.viewController.navigationController setProgress:completed.floatValue animated:YES];
-		}];
-    }
-    return self;
+		}
+	}
 }
 
-- (void) addToViewController:(UIViewController *) vc {
-	self.viewController = vc;
+- (void) updateProgress:(CGFloat) progress {
+	DDLogInfo(@"Progress: %f",progress);
+	if (self.progress.running) [self.viewController.navigationController setProgress:progress animated:YES];
 }
 
 @end

bmf/ios/subspecs/m13/BMFM13ProgressView.h

 
 #import <Foundation/Foundation.h>
 
-#import "BMFLoaderViewProtocol.h"
+#import "BMFProgressUI.h"
 
 @class M13ProgressView;
 
-@interface BMFM13ProgressView : NSObject <BMFLoaderViewProtocol>
-
-@property (nonatomic, strong) NSString *message;
-
-@property (nonatomic, strong) BMFProgress *progress;
-
-@property (nonatomic, copy) BMFActionBlock reloadActionBlock;
+@interface BMFM13ProgressView : BMFProgressUI
 
 - (instancetype) initWithView:(M13ProgressView *) progressView;
 

bmf/ios/subspecs/m13/BMFM13ProgressView.m

     self = [super init];
     if (self) {
         self.progressView = progressView;
-		_progress = [BMFProgress new];
-		
-		@weakify(self);
-		[[RACObserve(self, progress.running) deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNumber *runningNumber) {
-			@strongify(self);
-			if (runningNumber.boolValue) {
-				[self.progressView setProgress:self.progress.fractionCompleted animated:NO];
-				self.progressView.alpha = 1;
-			}
-			else {
-				if (self.progress.fractionCompleted==1) {
-					if (self.progress.failedError) {
-						[self.progressView performAction:M13ProgressViewActionFailure animated:YES];
-					}
-					else {
-						[self.progressView performAction:M13ProgressViewActionSuccess animated:YES];
-					}
-				}
-			}
-		}];
-		[[RACObserve(self, progress.fractionCompleted) deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNumber *completed) {
-			@strongify(self);
-			[self.progressView setProgress:completed.floatValue animated:YES];
-		}];
-    }
+	}
     return self;
 }
 
 	[BMFAutoLayoutUtils centerView:self.progressView inParent:vc.view];
 }
 
+- (void) updateRunning: (BOOL) running {
+	if (running) {
+		[self.progressView setProgress:self.progress.fractionCompleted animated:NO];
+		self.progressView.alpha = 1;
+	}
+	else {
+		if (self.progress.fractionCompleted==1) {
+			if (self.progress.failedError) {
+				[self.progressView performAction:M13ProgressViewActionFailure animated:YES];
+			}
+			else {
+				[self.progressView performAction:M13ProgressViewActionSuccess animated:YES];
+			}
+		}
+	}
+}
+
+- (void) updateProgress:(CGFloat) progress {
+	[self.progressView setProgress:progress animated:YES];
+}
+
 @end

bmf/shared/utils/BMFEaseUtils.h

+//
+//  BMFEaseUtils.h
+//  Pods
+//
+//  Created by Jose Manuel Sánchez Peñarroja on 02/06/14.
+//
+//
+
+#import <Foundation/Foundation.h>
+
+@interface BMFEaseUtils : NSObject
+
++ (CGFloat) quadraticEaseIn:(CGFloat) value;
++ (CGFloat) quadraticEaseOut:(CGFloat) value;
+
++ (CGFloat) cubicEaseIn:(CGFloat) value;
++ (CGFloat) cubicEaseOut:(CGFloat) value;
+
++ (CGFloat) quarticEaseIn:(CGFloat) value;
++ (CGFloat) quarticEaseOut:(CGFloat) value;
+
++ (CGFloat) circularEaseIn:(CGFloat) value;
++ (CGFloat) circularEaseOut:(CGFloat) value;
+
+@end

bmf/shared/utils/BMFEaseUtils.m

+//
+//  BMFEaseUtils.m
+//  Pods
+//
+//  Created by Jose Manuel Sánchez Peñarroja on 02/06/14.
+//
+//
+
+#import "BMFEaseUtils.h"
+
+@implementation BMFEaseUtils
+
++ (CGFloat) quadraticEaseIn:(CGFloat) value {
+	return value*value;
+}
+
++ (CGFloat) quadraticEaseOut:(CGFloat) value {
+	return -value*(value-2);
+}
+
++ (CGFloat) cubicEaseIn:(CGFloat) value {
+	return value*value*value;
+}
+
++ (CGFloat) cubicEaseOut:(CGFloat) value {
+	value--;
+	return value*value*value+1;
+}
+
++ (CGFloat) quarticEaseIn:(CGFloat) value {
+	value *= value;
+	return value*value;
+}
+
++ (CGFloat) quarticEaseOut:(CGFloat) value {
+	value--;
+	value *= value;
+	return -(value*value-1);
+}
+
++ (CGFloat) circularEaseIn:(CGFloat) value {
+	return -(sqrt(1 - value*value) - 1);
+}
+
++ (CGFloat) circularEaseOut:(CGFloat) value {
+	value--;
+	return (sqrt(1 - value*value));
+}
+
+@end

bmf/shared/views/BMFProgressUI.h

+//
+//  BMFProgressUI.h
+//  Pods
+//
+//  Created by Jose Manuel Sánchez Peñarroja on 02/06/14.
+//
+//
+
+#import <Foundation/Foundation.h>
+
+#import "BMFLoaderViewProtocol.h"
+
+@interface BMFProgressUI : NSObject <BMFLoaderViewProtocol>
+
+@property (nonatomic, strong) NSString *message;
+
+@property (nonatomic, strong) BMFProgress *progress;
+
+@property (nonatomic, copy) BMFActionBlock reloadActionBlock;
+
+
+- (CGFloat) displayedProgressWithFractionCompleted:(CGFloat) fractionCompleted;
+
+/// Template method to be implemented by subclasses to update the view
+- (void) updateRunning: (BOOL) running;
+
+/// Template method to be implemented by subclasses to update the view
+- (void) updateProgress:(CGFloat) progress;
+
+@end

bmf/shared/views/BMFProgressUI.m

+//
+//  BMFProgressUI.m
+//  Pods
+//
+//  Created by Jose Manuel Sánchez Peñarroja on 02/06/14.
+//
+//
+
+#import "BMFProgressUI.h"
+
+#import <ReactiveCocoa/ReactiveCocoa.h>
+#import <ReactiveCocoa/RACEXTScope.h>
+
+#import "BMFEaseUtils.h"
+
+@interface BMFProgressUI()
+
+@property (nonatomic, assign) CGFloat currentProgress;
+
+@end
+
+@implementation BMFProgressUI
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+		_progress = [BMFProgress new];
+		
+		@weakify(self);
+		[[RACObserve(self, progress.running) deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNumber *runningNumber) {
+			@strongify(self);
+			[self updateRunning:runningNumber.boolValue];
+		}];
+		[[RACObserve(self, progress.fractionCompleted) deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNumber *completed) {
+			@strongify(self);
+			[self updateProgress:[self displayedProgressWithFractionCompleted:completed.floatValue]];
+		}];
+    }
+    return self;
+}
+
+- (CGFloat) displayedProgressWithFractionCompleted:(CGFloat) fractionCompleted {
+	CGFloat result;
+	
+	// Adjust the value so it's faster when finishing
+	CGFloat value = [BMFEaseUtils circularEaseIn:fractionCompleted];
+	
+	// Don't allow to go back
+	if (value>=self.currentProgress) result = value;
+	else {
+		if (value==0 && self.currentProgress==1) result = value;
+		else result = self.currentProgress;
+	}
+	
+	self.currentProgress = result;
+
+	return self.currentProgress;
+}
+
+#pragma mark Template methods
+
+- (void) addToViewController:(UIViewController *)vc {
+	BMFAbstractMethod();
+}
+
+- (void) updateRunning: (BOOL) running {
+	BMFAbstractMethod();
+}
+
+- (void) updateProgress:(CGFloat) progress {
+	BMFAbstractMethod();
+}
+	
+@end