diff --git a/BAPromise.podspec b/BAPromise.podspec index 6525c5b..ef88618 100644 --- a/BAPromise.podspec +++ b/BAPromise.podspec @@ -16,8 +16,8 @@ s.osx.deployment_target = '10.10' s.tvos.deployment_target = '9.0' s.requires_arc = true -s.source_files = 'Classes/*' +s.source_files = 'Classes/*', 'Categories/*' -s.public_header_files = 'Classes/BAPromise.h' +s.public_header_files = 'Classes/BAPromise.h', 'Categories/*.h' end \ No newline at end of file diff --git a/BAPromise.xcodeproj/project.pbxproj b/BAPromise.xcodeproj/project.pbxproj index 39df6ee..587d137 100644 --- a/BAPromise.xcodeproj/project.pbxproj +++ b/BAPromise.xcodeproj/project.pbxproj @@ -40,6 +40,9 @@ E7B8D23A1B7E6D0200823BFC /* TestWaiter.h in Sources */ = {isa = PBXBuildFile; fileRef = E7B8D2221B7E6CDF00823BFC /* TestWaiter.h */; }; E7B8D23B1B7E6D0200823BFC /* TestWaiter.m in Sources */ = {isa = PBXBuildFile; fileRef = E7B8D2231B7E6CDF00823BFC /* TestWaiter.m */; }; E7B8D23C1B7E6D0200823BFC /* ThenTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7B8D2241B7E6CDF00823BFC /* ThenTests.m */; }; + E7C2C0791CC9160800D271CC /* UIViewController+BAPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = E7C2C0781CC9160800D271CC /* UIViewController+BAPromise.m */; }; + E7C2C07D1CC971BC00D271CC /* UIViewControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7C2C07C1CC971BC00D271CC /* UIViewControllerTests.m */; }; + E7C2C07E1CC9724100D271CC /* UIViewController+BAPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = E7C2C0781CC9160800D271CC /* UIViewController+BAPromise.m */; }; E7CA16FD1BB9B0FC002D7196 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E7CA16FC1BB9B0FC002D7196 /* main.m */; }; E7CA17001BB9B0FC002D7196 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E7CA16FF1BB9B0FC002D7196 /* AppDelegate.m */; }; E7CA17031BB9B0FC002D7196 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E7CA17021BB9B0FC002D7196 /* ViewController.m */; }; @@ -126,6 +129,9 @@ E7B8D2221B7E6CDF00823BFC /* TestWaiter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestWaiter.h; path = BAPromiseTests/TestWaiter.h; sourceTree = ""; }; E7B8D2231B7E6CDF00823BFC /* TestWaiter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TestWaiter.m; path = BAPromiseTests/TestWaiter.m; sourceTree = ""; }; E7B8D2241B7E6CDF00823BFC /* ThenTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ThenTests.m; path = BAPromiseTests/ThenTests.m; sourceTree = ""; }; + E7C2C0771CC9160800D271CC /* UIViewController+BAPromise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+BAPromise.h"; sourceTree = ""; }; + E7C2C0781CC9160800D271CC /* UIViewController+BAPromise.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+BAPromise.m"; sourceTree = ""; }; + E7C2C07C1CC971BC00D271CC /* UIViewControllerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIViewControllerTests.m; sourceTree = ""; }; E7CA16F91BB9B0FC002D7196 /* tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tvOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; E7CA16FC1BB9B0FC002D7196 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; E7CA16FE1BB9B0FC002D7196 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; @@ -206,6 +212,7 @@ E712B3231B7E6B4800590AA8 = { isa = PBXGroup; children = ( + E7C2C0761CC915DA00D271CC /* Categories */, E7B8D22C1B7E6CE400823BFC /* Tests */, E712B3771B7E6B8000590AA8 /* Classes */, E712B32E1B7E6B4800590AA8 /* OS X */, @@ -317,10 +324,20 @@ E7B8D2231B7E6CDF00823BFC /* TestWaiter.m */, E7B8D2241B7E6CDF00823BFC /* ThenTests.m */, E7E3E8CF1CBD511F00C55538 /* WhenTests.m */, + E7C2C07C1CC971BC00D271CC /* UIViewControllerTests.m */, ); name = Tests; sourceTree = ""; }; + E7C2C0761CC915DA00D271CC /* Categories */ = { + isa = PBXGroup; + children = ( + E7C2C0771CC9160800D271CC /* UIViewController+BAPromise.h */, + E7C2C0781CC9160800D271CC /* UIViewController+BAPromise.m */, + ); + path = Categories; + sourceTree = ""; + }; E7CA16FA1BB9B0FC002D7196 /* tvOS */ = { isa = PBXGroup; children = ( @@ -731,6 +748,7 @@ buildActionMask = 2147483647; files = ( E712B3341B7E6B4800590AA8 /* main.m in Sources */, + E7C2C0791CC9160800D271CC /* UIViewController+BAPromise.m in Sources */, E7B8D21B1B7E6CB000823BFC /* BAPromise.m in Sources */, E712B3311B7E6B4800590AA8 /* AppDelegate.m in Sources */, ); @@ -757,6 +775,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E7C2C07E1CC9724100D271CC /* UIViewController+BAPromise.m in Sources */, E7B8D21C1B7E6CC300823BFC /* BAPromise.m in Sources */, E712B35C1B7E6B7900590AA8 /* ViewController.m in Sources */, E712B3591B7E6B7800590AA8 /* AppDelegate.m in Sources */, @@ -776,6 +795,7 @@ E7B8D2391B7E6D0200823BFC /* RejectTests.m in Sources */, E7B8D23A1B7E6D0200823BFC /* TestWaiter.h in Sources */, E7B8D23B1B7E6D0200823BFC /* TestWaiter.m in Sources */, + E7C2C07D1CC971BC00D271CC /* UIViewControllerTests.m in Sources */, E7B8D23C1B7E6D0200823BFC /* ThenTests.m in Sources */, E712B36F1B7E6B7900590AA8 /* iOSTests.m in Sources */, ); diff --git a/Categories/UIViewController+BAPromise.h b/Categories/UIViewController+BAPromise.h new file mode 100644 index 0000000..7673e9d --- /dev/null +++ b/Categories/UIViewController+BAPromise.h @@ -0,0 +1,24 @@ +// +// UIViewController+BAPromise.h +// BAPromise +// +// Created by Ben Allison on 4/21/16. +// Copyright © 2016 Ben Allison. All rights reserved. +// + +#import +#import "BAPromise.h" + +@interface UIViewController (BAPromise) + +-(BAPromise *)promiseDismissViewControllerAnimated:(BOOL)animated; +-(BAPromise *)promisePresentViewController:(UIViewController *)controller + animated:(BOOL)animated; +- (BAPromise *)transitionFromViewController:(UIViewController *)fromViewController + toViewController:(UIViewController *)toViewController + duration:(NSTimeInterval)duration + options:(UIViewAnimationOptions)options + animations:(void (^ __nullable)(void))animations + completion:(void (^ __nullable)(BOOL finished))completion; + +@end diff --git a/Categories/UIViewController+BAPromise.m b/Categories/UIViewController+BAPromise.m new file mode 100644 index 0000000..530f5df --- /dev/null +++ b/Categories/UIViewController+BAPromise.m @@ -0,0 +1,56 @@ +// +// UIViewController+BAPromise.m +// BAPromise +// +// Created by Ben Allison on 4/21/16. +// Copyright © 2016 Ben Allison. All rights reserved. +// + +#import "UIViewController+BAPromise.h" +#import "BAPromise.h" + +@implementation UIViewController (BAPromise) + +-(BAPromise *)promiseDismissViewControllerAnimated:(BOOL)animated +{ + BAPromiseClient *promise = BAPromiseClient.new; + if (!self.presentedViewController) { + // TODO(benski) a better error + return [BAPromiseClient rejectedPromise:[NSError errorWithDomain:@"org.benski.promise" code:0 userInfo:nil]]; + } + + [self dismissViewControllerAnimated:animated completion:^{ + [promise fulfill]; + }]; + return promise; +} + +-(BAPromise *)promisePresentViewController:(UIViewController *)controller + animated:(BOOL)animated +{ + BAPromiseClient *promise = BAPromiseClient.new; + [self presentViewController:controller animated:YES completion:^{ + [promise fulfill]; + }]; + return promise; +} + +- (BAPromise *)promiseTransitionFromViewController:(UIViewController *)fromViewController + toViewController:(UIViewController *)toViewController + duration:(NSTimeInterval)duration + options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations + completion:(void (^ __nullable)(BOOL finished))completion +{ + BAPromiseClient *promise = BAPromiseClient.new; + [self transitionFromViewController:fromViewController + toViewController:toViewController + duration:duration + options:options + animations:animations + completion:^(BOOL finished) { + [promise fulfillWithObject:@(finished)]; + }]; + return promise; +} + +@end diff --git a/UIViewControllerTests.m b/UIViewControllerTests.m new file mode 100644 index 0000000..a6f6e37 --- /dev/null +++ b/UIViewControllerTests.m @@ -0,0 +1,69 @@ +// +// UIViewController+BAPromiseTests.m +// BAPromise +// +// Created by Ben Allison on 4/21/16. +// Copyright © 2016 Ben Allison. All rights reserved. +// + +#import +#import "UIViewController+BAPromise.h" + +@interface UIViewController_BAPromiseTests : XCTestCase + +@end + +@implementation UIViewController_BAPromiseTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testPresentAnimated { + + UIViewController *vc = UIViewController.new; + UIViewController *present = UIViewController.new; + UIApplication.sharedApplication.keyWindow.rootViewController = vc; + XCTestExpectation *expectation = [self expectationWithDescription:@"Promise should fulfill"]; + + [[vc promisePresentViewController:present animated:YES] done:^(id obj) { + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:1.0 handler:nil]; +} + +- (void)testPresentNonAnimated { + + UIViewController *vc = UIViewController.new; + UIViewController *present = UIViewController.new; + UIApplication.sharedApplication.keyWindow.rootViewController = vc; + XCTestExpectation *expectation = [self expectationWithDescription:@"Promise should fulfill"]; + + [[vc promisePresentViewController:present animated:NO] done:^(id obj) { + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:1.0 handler:nil]; +} + +- (void)testDismiss { + + UIViewController *vc = UIViewController.new; + UIViewController *present = UIViewController.new; + UIApplication.sharedApplication.keyWindow.rootViewController = vc; + XCTestExpectation *expectation = [self expectationWithDescription:@"Promise should fulfill"]; + + [[[vc promisePresentViewController:present animated:YES] then:^(id obj) { + return [vc promiseDismissViewControllerAnimated:YES]; + }] done:^(id obj) { + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:4.0 handler:nil]; +} + +@end