Skip to content

Commit 68c85ea

Browse files
committed
Refactoring navigation hierarchy
Former-commit-id: 91b1bdc
1 parent 4158e05 commit 68c85ea

10 files changed

+70
-82
lines changed

MVVMReactiveCocoa/MRCAppDelegate.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88

99
#import <UIKit/UIKit.h>
1010
#import "Reachability.h"
11-
12-
@class MRCNavigationControllerStack;
11+
#import "MRCNavigationControllerStack.h"
1312

1413
@interface MRCAppDelegate : UIResponder <UIApplicationDelegate>
1514

MVVMReactiveCocoa/MRCAppDelegate.m

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
3737
self.services = [[MRCViewModelServicesImpl alloc] init];
3838
self.navigationControllerStack = [[MRCNavigationControllerStack alloc] initWithServices:self.services];
3939

40-
UINavigationController *navigationController = [[MRCNavigationController alloc] initWithRootViewController:self.createInitialViewController];
41-
[self.navigationControllerStack pushNavigationController:navigationController];
42-
4340
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
44-
self.window.rootViewController = navigationController;
41+
[self.services resetRootViewModel:[self createInitialViewModel]];
4542
[self.window makeKeyAndVisible];
4643

4744
[self configureAppearance];
@@ -56,20 +53,18 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
5653
return YES;
5754
}
5855

59-
- (UIViewController *)createInitialViewController {
56+
- (id<MRCViewModelProtocol>)createInitialViewModel {
6057
// The user has logged-in.
6158
if ([SSKeychain rawLogin].isExist && [SSKeychain accessToken].isExist) {
6259
// Some OctoKit APIs will use the `login` property of `OCTUser`.
6360
OCTUser *user = [OCTUser mrc_userWithRawLogin:[SSKeychain rawLogin] server:OCTServer.dotComServer];
6461

6562
OCTClient *authenticatedClient = [OCTClient authenticatedClientWithUser:user token:[SSKeychain accessToken]];
6663
self.services.client = authenticatedClient;
67-
self.viewModel = [[MRCHomepageViewModel alloc] initWithServices:self.services params:nil];
6864

69-
return [[MRCHomepageViewController alloc] initWithViewModel:self.viewModel];
65+
return [[MRCHomepageViewModel alloc] initWithServices:self.services params:nil];
7066
} else {
71-
self.viewModel = [[MRCLoginViewModel alloc] initWithServices:self.services params:nil];
72-
return [[MRCLoginViewController alloc] initWithViewModel:self.viewModel];
67+
return [[MRCLoginViewModel alloc] initWithServices:self.services params:nil];
7368
}
7469
}
7570

MVVMReactiveCocoa/View/BaseClass/MRCNavigationControllerStack.m

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ - (void)registerNavigationHooks {
6464
subscribeNext:^(RACTuple *tuple) {
6565
@strongify(self)
6666
UIViewController *viewController = (UIViewController *)[MRCRouter.sharedInstance viewControllerForViewModel:tuple.first];
67+
viewController.hidesBottomBarWhenPushed = YES;
6768
[self.navigationControllers.lastObject pushViewController:viewController animated:[tuple.second boolValue]];
6869
}];
6970

@@ -108,15 +109,15 @@ - (void)registerNavigationHooks {
108109
rac_signalForSelector:@selector(resetRootViewModel:)]
109110
subscribeNext:^(RACTuple *tuple) {
110111
@strongify(self)
112+
[self.navigationControllers removeAllObjects];
113+
111114
UIViewController *viewController = (UIViewController *)[MRCRouter.sharedInstance viewControllerForViewModel:tuple.first];
112-
113-
if (![viewController isKindOfClass:UINavigationController.class]) {
115+
116+
if (![viewController isKindOfClass:[UINavigationController class]] && ![viewController isKindOfClass:[UITabBarController class]]) {
114117
viewController = [[MRCNavigationController alloc] initWithRootViewController:viewController];
118+
[self pushNavigationController:(UINavigationController *)viewController];
115119
}
116120

117-
[self.navigationControllers removeAllObjects];
118-
[self pushNavigationController:(UINavigationController *)viewController];
119-
120121
MRCSharedAppDelegate.window.rootViewController = viewController;
121122
}];
122123
}

MVVMReactiveCocoa/View/MRCHomepageViewController.m

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,14 @@
1313
#import "MRCNewsViewModel.h"
1414
#import "MRCReposViewModel.h"
1515
#import "MRCProfileViewModel.h"
16-
#import "MRCNavigationControllerStack.h"
1716
#import "MRCReposViewController.h"
1817
#import "MRCNavigationController.h"
1918
#import "MRCSearchViewController.h"
2019
#import "MRCUserListViewModel.h"
2120

2221
@interface MRCHomepageViewController () <UITabBarControllerDelegate>
2322

24-
@property (nonatomic, strong, readonly) MRCHomepageViewModel *viewModel;
25-
26-
@property (nonatomic, strong) MRCNewsViewController *newsViewController;
27-
@property (nonatomic, strong) MRCReposViewController *reposViewController;
28-
@property (nonatomic, strong) MRCSearchViewController *searchViewController;
29-
@property (nonatomic, strong) MRCProfileViewController *profileViewController;
23+
@property (nonatomic, strong) MRCHomepageViewModel *viewModel;
3024

3125
@end
3226

@@ -36,45 +30,55 @@ @implementation MRCHomepageViewController
3630

3731
- (void)viewDidLoad {
3832
[super viewDidLoad];
39-
33+
4034
self.automaticallyAdjustsScrollViewInsets = NO;
35+
36+
UINavigationController *newsNavigationController = ({
37+
MRCNewsViewController *newsViewController = [[MRCNewsViewController alloc] initWithViewModel:self.viewModel.newsViewModel];
38+
39+
UIImage *newsImage = [UIImage octicon_imageWithIdentifier:@"Rss" size:CGSizeMake(25, 25)];
40+
newsViewController.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"News" image:newsImage tag:1];
41+
42+
[[MRCNavigationController alloc] initWithRootViewController:newsViewController];
43+
});
4144

42-
self.newsViewController = [[MRCNewsViewController alloc] initWithViewModel:self.viewModel.newsViewModel];
43-
UIImage *newsImage = [UIImage octicon_imageWithIdentifier:@"Rss" size:CGSizeMake(25, 25)];
44-
self.newsViewController.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"News" image:newsImage tag:1];
45-
46-
self.reposViewController = [[MRCReposViewController alloc] initWithViewModel:self.viewModel.reposViewModel];
47-
UIImage *reposImage = [UIImage octicon_imageWithIdentifier:@"Repo" size:CGSizeMake(25, 25)];
48-
self.reposViewController.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"Repositories" image:reposImage tag:2];
49-
50-
self.searchViewController = [[MRCSearchViewController alloc] initWithViewModel:self.viewModel.searchViewModel];
51-
UIImage *searchImage = [UIImage octicon_imageWithIdentifier:@"Search" size:CGSizeMake(25, 25)];
52-
self.searchViewController.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"Search" image:searchImage tag:3];
45+
UINavigationController *reposNavigationController = ({
46+
MRCReposViewController *reposViewController = [[MRCReposViewController alloc] initWithViewModel:self.viewModel.reposViewModel];
47+
48+
UIImage *reposImage = [UIImage octicon_imageWithIdentifier:@"Repo" size:CGSizeMake(25, 25)];
49+
reposViewController.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"Repositories" image:reposImage tag:2];
50+
51+
[[MRCNavigationController alloc] initWithRootViewController:reposViewController];
52+
});
5353

54-
UIImage *profileImage = [UIImage octicon_imageWithIdentifier:@"Person" size:CGSizeMake(25, 25)];
55-
self.profileViewController = [[MRCProfileViewController alloc] initWithViewModel:self.viewModel.profileViewModel];
56-
self.profileViewController.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"Profile" image:profileImage tag:4];
54+
UINavigationController *searchNavigationController = ({
55+
MRCSearchViewController *searchViewController = [[MRCSearchViewController alloc] initWithViewModel:self.viewModel.searchViewModel];
56+
57+
UIImage *searchImage = [UIImage octicon_imageWithIdentifier:@"Search" size:CGSizeMake(25, 25)];
58+
searchViewController.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"Search" image:searchImage tag:3];
59+
60+
[[MRCNavigationController alloc] initWithRootViewController:searchViewController];
61+
});
5762

58-
self.viewControllers = @[ self.newsViewController, self.reposViewController, self.searchViewController, self.profileViewController ];
63+
UINavigationController *profileNavigationController = ({
64+
MRCProfileViewController *profileViewController = [[MRCProfileViewController alloc] initWithViewModel:self.viewModel.profileViewModel];
65+
66+
UIImage *profileImage = [UIImage octicon_imageWithIdentifier:@"Person" size:CGSizeMake(25, 25)];
67+
profileViewController.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"Profile" image:profileImage tag:4];
68+
69+
[[MRCNavigationController alloc] initWithRootViewController:profileViewController];
70+
});
71+
72+
self.viewControllers = @[ newsNavigationController, reposNavigationController, searchNavigationController, profileNavigationController ];
73+
74+
[MRCSharedAppDelegate.navigationControllerStack pushNavigationController:newsNavigationController];
5975

60-
[[[self
76+
[[self
6177
rac_signalForSelector:@selector(tabBarController:didSelectViewController:)
6278
fromProtocol:@protocol(UITabBarControllerDelegate)]
63-
startWith:RACTuplePack(self, self.newsViewController)]
6479
subscribeNext:^(RACTuple *tuple) {
65-
RACTupleUnpack(UITabBarController *tabBarController, UIViewController *viewController) = tuple;
66-
67-
tabBarController.navigationItem.title = [((MRCViewController *)viewController).viewModel title];
68-
69-
if (viewController.tabBarItem.tag == 1) {
70-
tabBarController.navigationItem.titleView = nil;
71-
} else if (viewController.tabBarItem.tag == 2) {
72-
tabBarController.navigationItem.titleView = ((MRCReposViewController *)viewController).segmentedControl;
73-
} else if (viewController.tabBarItem.tag == 3) {
74-
tabBarController.navigationItem.titleView = ((MRCSearchViewController *)viewController).searchController.searchBar;
75-
} else if (viewController.tabBarItem.tag == 4) {
76-
tabBarController.navigationItem.titleView = nil;
77-
}
80+
[MRCSharedAppDelegate.navigationControllerStack popNavigationController];
81+
[MRCSharedAppDelegate.navigationControllerStack pushNavigationController:tuple.second];
7882
}];
7983
self.delegate = self;
8084
}

MVVMReactiveCocoa/View/MRCNewsViewController.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ @implementation MRCNewsViewController
2525
- (void)viewDidLoad {
2626
[super viewDidLoad];
2727

28+
self.automaticallyAdjustsScrollViewInsets = NO;
29+
2830
[self.tableView registerNib:[UINib nibWithNibName:@"MRCNewsTableViewCell" bundle:nil] forCellReuseIdentifier:@"MRCNewsTableViewCell"];
2931

3032
if (self.viewModel.type == MRCNewsViewModelTypeNews) {

MVVMReactiveCocoa/View/MRCProfileViewController.m

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,10 @@ - (void)viewDidLoad {
4343
self.tableView.tableHeaderView = self.tableHeaderView;
4444

4545
@weakify(self)
46-
[RACObserve(self.viewModel, user)
47-
subscribeNext:^(id x) {
48-
@strongify(self)
49-
[self.tableView reloadData];
50-
}];
46+
[RACObserve(self.viewModel, user) subscribeNext:^(id x) {
47+
@strongify(self)
48+
[self.tableView reloadData];
49+
}];
5150
}
5251

5352
- (UIEdgeInsets)contentInset {

MVVMReactiveCocoa/View/MRCRepoDetailViewController.m

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,6 @@ @implementation MRCRepoDetailViewController
2828

2929
@dynamic viewModel;
3030

31-
- (instancetype)initWithViewModel:(id<MRCViewModelProtocol>)viewModel {
32-
self = [super initWithViewModel:viewModel];
33-
if (self) {
34-
self.hidesBottomBarWhenPushed = YES;
35-
}
36-
return self;
37-
}
38-
3931
- (void)viewDidLoad {
4032
[super viewDidLoad];
4133

MVVMReactiveCocoa/View/MRCReposViewController.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,17 @@ @implementation MRCReposViewController
2424
- (void)viewDidLoad {
2525
[super viewDidLoad];
2626

27+
self.automaticallyAdjustsScrollViewInsets = NO;
28+
2729
MRCOwnedReposViewController *ownedReposViewController = [[MRCOwnedReposViewController alloc] initWithViewModel:self.viewModel.viewModels[0]];
2830
ownedReposViewController.segmentedControlItem = @"Owned";
2931

3032
MRCStarredReposViewController *starredReposViewController = [[MRCStarredReposViewController alloc] initWithViewModel:self.viewModel.viewModels[1]];
3133
starredReposViewController.segmentedControlItem = @"Starred";
3234

3335
self.viewControllers = @[ ownedReposViewController, starredReposViewController ];
36+
37+
self.navigationItem.titleView = self.segmentedControl;
3438
}
3539

3640
@end

MVVMReactiveCocoa/View/MRCSearchViewController.m

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ @implementation MRCSearchViewController
2525
- (void)viewDidLoad {
2626
[super viewDidLoad];
2727

28+
self.automaticallyAdjustsScrollViewInsets = NO;
29+
2830
self.tableView.tableFooterView = nil;
2931

3032
self.searchResultsController = [[MRCReposSearchResultsViewController alloc] initWithViewModel:self.viewModel.searchResultsViewModel];
@@ -34,6 +36,10 @@ - (void)viewDidLoad {
3436
self.searchController.searchBar.tintColor = HexRGB(colorI5);
3537
self.searchController.searchBar.delegate = self.searchResultsController;
3638
self.searchController.delegate = self;
39+
40+
self.navigationItem.titleView = self.searchController.searchBar;
41+
42+
self.definesPresentationContext = YES;
3743
}
3844

3945
- (UIEdgeInsets)contentInset {
@@ -44,12 +50,6 @@ - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPa
4450
cell.textLabel.text = search.keyword;
4551
}
4652

47-
#pragma mark - UISearchControllerDelegate
48-
49-
- (void)presentSearchController:(UISearchController *)searchController {
50-
[self presentViewController:searchController animated:YES completion:NULL];
51-
}
52-
5353
#pragma mark - UITableViewDataSource
5454

5555
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
@@ -95,7 +95,7 @@ - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleFo
9595
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
9696
[tableView deselectRowAtIndexPath:indexPath animated:YES];
9797

98-
[self presentSearchController:self.searchController];
98+
[self presentViewController:self.searchController animated:YES completion:NULL];
9999

100100
MRCSearch *search = self.viewModel.dataSource[indexPath.section][indexPath.row];
101101
self.searchController.searchBar.text = search.keyword;

MVVMReactiveCocoa/View/MRCSettingsViewController.m

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,6 @@ @implementation MRCSettingsViewController
2020

2121
@dynamic viewModel;
2222

23-
- (instancetype)initWithViewModel:(id<MRCViewModelProtocol>)viewModel {
24-
self = [super initWithViewModel:viewModel];
25-
if (self) {
26-
self.hidesBottomBarWhenPushed = YES;
27-
}
28-
return self;
29-
}
30-
3123
- (void)viewDidLoad {
3224
[super viewDidLoad];
3325
self.viewModel.adURL = MRCSharedAppDelegate.adURL;

0 commit comments

Comments
 (0)