-
-
Notifications
You must be signed in to change notification settings - Fork 632
Expand file tree
/
Copy pathRNSStackNavigationController.mm
More file actions
80 lines (66 loc) · 2.54 KB
/
RNSStackNavigationController.mm
File metadata and controls
80 lines (66 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#import "RNSStackNavigationController.h"
#import "RNSLog.h"
#import "RNSStackOperation.h"
#import "React/RCTAssert.h"
@implementation RNSStackNavigationController {
NSMutableArray<RNSPushOperation *> *_Nonnull _pendingPushOperations;
NSMutableArray<RNSPopOperation *> *_Nonnull _pendingPopOperations;
}
- (instancetype)init
{
if (self = [super init]) {
[self initState];
}
return self;
}
- (void)initState
{
_pendingPushOperations = [NSMutableArray array];
_pendingPopOperations = [NSMutableArray array];
}
- (BOOL)hasPendingOperations
{
return _pendingPushOperations.count > 0 || _pendingPopOperations.count > 0;
}
- (void)enqueuePushOperation:(nonnull RNSStackScreenComponentView *)stackScreen
{
RNSPushOperation *operation = [[RNSPushOperation alloc] initWithScreen:stackScreen];
[_pendingPushOperations addObject:operation];
}
- (void)enqueuePopOperation:(nonnull RNSStackScreenComponentView *)stackScreen
{
RNSPopOperation *operation = [[RNSPopOperation alloc] initWithScreen:stackScreen];
[_pendingPopOperations addObject:operation];
}
- (void)performContainerUpdateIfNeeded
{
// NOTE: We consider UINavigationController.viewControllers to be part of
// the internal state of our stack implementation and expect it to be
// *synchronously* updated by UIKit while we perform our pop and push operations
//
// The assertions below work under this assumption
if ([self hasPendingOperations]) {
for (RNSPopOperation *op in _pendingPopOperations) {
UIViewController *controller = static_cast<UIViewController *>(op.stackScreen.controller);
RCTAssert([self.viewControllers count] > 1, @"[RNScreens] Attempt to pop last screen from the stack");
RCTAssert(self.topViewController == controller, @"[RNScreens] Attempt to pop non-top screen");
[self popViewControllerAnimated:true];
}
for (RNSPushOperation *op in _pendingPushOperations) {
UIViewController *controller = static_cast<UIViewController *>(op.stackScreen.controller);
[self pushViewController:controller animated:true];
}
RCTAssert([self.viewControllers count] > 0, @"[RNScreens] Stack should never be empty after updates");
[self dumpStackModel];
[_pendingPopOperations removeAllObjects];
[_pendingPushOperations removeAllObjects];
}
}
- (void)dumpStackModel
{
RNSLog(@"[RNScreens] StackContainer [%ld] MODEL BEGIN", self.view.tag);
for (UIViewController *viewController in self.viewControllers) {
RNSLog(@"[RNScreens] %@", static_cast<RNSStackScreenComponentView *>(viewController.view).screenKey);
}
}
@end