Skip to content

Commit

Permalink
Merge pull request #2 from jeslyvarghese/master
Browse files Browse the repository at this point in the history
Add routes for executing blocks
  • Loading branch information
lightory committed Apr 1, 2014
2 parents 7a61567 + a5a2b29 commit c601b8b
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 30 deletions.
10 changes: 8 additions & 2 deletions HHRouter/HHRouter.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,15 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#import <Foundation/Foundation.h>

typedef id(^HHRouterBlock) (NSDictionary *parms);
@interface HHRouter : NSObject
+ (instancetype)shared;

- (void)map:(NSString *)route toControllerClass:(Class)controllerClass;
- (UIViewController *)match:(NSString *)route;
- (UIViewController *)match:(NSString *)route __attribute__((deprecated));
- (UIViewController *)matchController:(NSString*)route;

- (void)map:(NSString *)route toBlock:(HHRouterBlock)block;
- (HHRouterBlock)matchBlock:(NSString*)route;
- (id)callBlock:(NSString*)route;
@end
96 changes: 78 additions & 18 deletions HHRouter/HHRouter.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#import "HHRouter.h"
#import <objc/runtime.h>

@interface HHRouter ()
@property (strong, nonatomic) NSMutableDictionary *routes;
Expand All @@ -39,24 +40,54 @@ + (instancetype)shared
return router;
}

- (void)map:(NSString *)route toControllerClass:(Class)controllerClass
- (void)map:(NSString *)route toBlock:(HHRouterBlock)block
{
NSArray *pathComponents = [self pathComponentsFromRoute:route];
NSMutableDictionary *subRoutes = [self subRoutesToRoute:route];
subRoutes[@"_"] = [block copy];
}

- (UIViewController *)matchController:(NSString *)route
{
NSDictionary *params = [self paramsInRoute:route];
Class controllerClass = params[@"controller_class"];

NSInteger index = 0;
NSMutableDictionary *subRoutes = self.routes;
while (index < pathComponents.count) {
NSString *pathComponent = pathComponents[index];
if (![subRoutes objectForKey:pathComponent]) {
subRoutes[pathComponent] = [[NSMutableDictionary alloc] init];
}
subRoutes = subRoutes[pathComponent];
index++;
UIViewController *viewController = [[controllerClass alloc] init];
if ([viewController respondsToSelector:@selector(setParams:)]) {
[viewController performSelector:@selector(setParams:) withObject:[params copy]];
}
subRoutes[@"_"] = controllerClass;
return viewController;
}

- (UIViewController *)match:(NSString *)route
{
return [self matchController:route];
}

- (HHRouterBlock)matchBlock:(NSString *)route
{
NSDictionary *params = [self paramsInRoute:route];
HHRouterBlock routerBlock = [params[@"block"] copy];
HHRouterBlock returnBlock = ^id(NSDictionary *aParams){
if (routerBlock) {
return routerBlock([params copy]);
}
return nil;
};
return [returnBlock copy];
}

- (id)callBlock:(NSString *)route
{
NSDictionary *params = [self paramsInRoute:route];
HHRouterBlock routerBlock = [params[@"block"] copy];
if (routerBlock) {
return routerBlock([params copy]);
}
return nil;
}

//extract params in a route
- (NSDictionary*)paramsInRoute:(NSString*)route
{
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"route"] = [self stringFromFilterAppUrlScheme:route];
Expand Down Expand Up @@ -95,13 +126,20 @@ - (UIViewController *)match:(NSString *)route
}
}
}

Class controllerClass = subRoutes[@"_"];
UIViewController *viewController = [[controllerClass alloc] init];
if ([viewController respondsToSelector:@selector(setParams:)]) {
[viewController performSelector:@selector(setParams:) withObject:[params copy]];
Class class = subRoutes[@"_"];
if (class_isMetaClass(object_getClass(class))) {
if ([class isSubclassOfClass:[UIViewController class]]) {
params[@"controller_class"] = subRoutes[@"_"];
} else {
return nil;
}
} else {
if (subRoutes[@"_"]) {
params[@"block"] = [subRoutes[@"_"] copy];
}
}
return viewController;

return [NSDictionary dictionaryWithDictionary:params];
}

#pragma mark - Private
Expand Down Expand Up @@ -150,4 +188,26 @@ - (NSArray *)appUrlSchemes
return [appUrlSchemes copy];
}

- (NSMutableDictionary*)subRoutesToRoute:(NSString*)route
{
NSArray *pathComponents = [self pathComponentsFromRoute:route];

NSInteger index = 0;
NSMutableDictionary *subRoutes = self.routes;
while (index < pathComponents.count) {
NSString *pathComponent = pathComponents[index];
if (![subRoutes objectForKey:pathComponent]) {
subRoutes[pathComponent] = [[NSMutableDictionary alloc] init];
}
subRoutes = subRoutes[pathComponent];
index++;
}
return subRoutes;
}

- (void)map:(NSString *)route toControllerClass:(Class)controllerClass
{
NSMutableDictionary *subRoutes = [self subRoutesToRoute:route];
subRoutes[@"_"] = controllerClass;
}
@end
6 changes: 1 addition & 5 deletions HHRouterExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@
A02D395A18D1B21F00291FE9 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
LastUpgradeCheck = 0510;
ORGANIZATIONNAME = Huohua;
TargetAttributes = {
A02D397C18D1B21F00291FE9 = {
Expand Down Expand Up @@ -326,7 +326,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
Expand Down Expand Up @@ -365,7 +364,6 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
Expand Down Expand Up @@ -425,7 +423,6 @@
A02D399218D1B22000291FE9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/HHRouterExample.app/HHRouterExample";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
Expand All @@ -449,7 +446,6 @@
A02D399318D1B22000291FE9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/HHRouterExample.app/HHRouterExample";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
Expand Down
30 changes: 25 additions & 5 deletions HHRouterExampleTests/HHRouterTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#import "UserViewController.h"
#import "StoryViewController.h"
#import "StoryListViewController.h"
#define TIME_OUT 5

@interface HHRouterTests : XCTestCase

Expand All @@ -34,19 +35,38 @@ - (void)testShared
XCTAssertTrue([[HHRouter shared] isEqual:[HHRouter shared]]);
}

- (void)testRouteBlocks
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

[[HHRouter shared]map:@"/user/add/" toBlock:^id(NSDictionary *parms) {
XCTAssertEqualObjects(parms[@"a"], @"1");
XCTAssertEqualObjects(parms[@"b"], @"2");
dispatch_semaphore_signal(semaphore);
}];

HHRouterBlock block = [[HHRouter shared]matchBlock:@"/user/add/?a=1&b=2"];
XCTAssertNotNil(block);
block(nil);
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) {
[[NSRunLoop currentRunLoop]runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:TIME_OUT]];
}
[[HHRouter shared]callBlock:@"/user/add/?a=1&b=2"];
}

- (void)testRoute
{
[[HHRouter shared] map:@"/user/:userId/" toControllerClass:[UserViewController class]];
[[HHRouter shared] map:@"/story/:storyId/" toControllerClass:[StoryViewController class]];
[[HHRouter shared] map:@"/user/:userId/story/" toControllerClass:[StoryListViewController class]];


XCTAssertEqualObjects([[[HHRouter shared] matchController:@"/story/2/"] class], [StoryViewController class]);
XCTAssertEqualObjects([[[HHRouter shared] matchController:@"/user/1/story/"] class], [StoryListViewController class]);

XCTAssertEqualObjects([[[HHRouter shared] match:@"/story/2/"] class], [StoryViewController class]);
XCTAssertEqualObjects([[[HHRouter shared] match:@"/user/1/story/"] class], [StoryListViewController class]);

XCTAssertEqualObjects([[[HHRouter shared] match:@"hhrouter://user/1/"] class], [UserViewController class]);
XCTAssertEqualObjects([[[HHRouter shared] matchController:@"hhrouter://user/1/"] class], [UserViewController class]);

UserViewController *userViewController = (UserViewController *) [[HHRouter shared] match:@"/user/1/?a=b&c=d"];
UserViewController *userViewController = (UserViewController *) [[HHRouter shared] matchController:@"/user/1/?a=b&c=d"];
XCTAssertEqualObjects(userViewController.params[@"route"], @"/user/1/?a=b&c=d");
XCTAssertEqualObjects(userViewController.params[@"userId"], @"1");
XCTAssertEqualObjects(userViewController.params[@"a"], @"b");
Expand Down

0 comments on commit c601b8b

Please sign in to comment.