[ReactNative] Use a single DisplayLink held by the bridge
This commit is contained in:
parent
4f8b2825a0
commit
75e4e124fa
|
@ -10,6 +10,7 @@
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
#import "RCTBridgeModule.h"
|
#import "RCTBridgeModule.h"
|
||||||
|
#import "RCTFrameUpdate.h"
|
||||||
#import "RCTInvalidating.h"
|
#import "RCTInvalidating.h"
|
||||||
#import "RCTJavaScriptExecutor.h"
|
#import "RCTJavaScriptExecutor.h"
|
||||||
|
|
||||||
|
@ -122,4 +123,14 @@ static const char *__rct_import_##module##_##method##__ = #module"."#method;
|
||||||
*/
|
*/
|
||||||
- (void)reload;
|
- (void)reload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new observer that will be called on every screen refresh
|
||||||
|
*/
|
||||||
|
- (void)addFrameUpdateObserver:(id<RCTFrameUpdateObserver>)observer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop receiving screen refresh updates for the given observer
|
||||||
|
*/
|
||||||
|
- (void)removeFrameUpdateObserver:(id<RCTFrameUpdateObserver>)observer;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -677,6 +677,73 @@ static NSDictionary *RCTLocalModulesConfig()
|
||||||
return localModules;
|
return localModules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@interface RCTDisplayLink : NSObject <RCTInvalidating>
|
||||||
|
|
||||||
|
- (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface RCTBridge (RCTDisplayLink)
|
||||||
|
|
||||||
|
- (void)_update:(CADisplayLink *)displayLink;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation RCTDisplayLink
|
||||||
|
{
|
||||||
|
__weak RCTBridge *_bridge;
|
||||||
|
CADisplayLink *_displayLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||||
|
{
|
||||||
|
if ((self = [super init])) {
|
||||||
|
_bridge = bridge;
|
||||||
|
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_update:)];
|
||||||
|
[_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isValid
|
||||||
|
{
|
||||||
|
return _displayLink != nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)invalidate
|
||||||
|
{
|
||||||
|
if (self.isValid) {
|
||||||
|
[_displayLink invalidate];
|
||||||
|
_displayLink = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_update:(CADisplayLink *)displayLink
|
||||||
|
{
|
||||||
|
[_bridge _update:displayLink];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface RCTFrameUpdate (Private)
|
||||||
|
|
||||||
|
- (instancetype)initWithDisplayLink:(CADisplayLink *)displayLink;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation RCTFrameUpdate
|
||||||
|
|
||||||
|
- (instancetype)initWithDisplayLink:(CADisplayLink *)displayLink
|
||||||
|
{
|
||||||
|
if ((self = [super init])) {
|
||||||
|
_timestamp = displayLink.timestamp;
|
||||||
|
_deltaTime = displayLink.duration;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation RCTBridge
|
@implementation RCTBridge
|
||||||
{
|
{
|
||||||
RCTSparseArray *_modulesByID;
|
RCTSparseArray *_modulesByID;
|
||||||
|
@ -685,6 +752,8 @@ static NSDictionary *RCTLocalModulesConfig()
|
||||||
Class _executorClass;
|
Class _executorClass;
|
||||||
NSURL *_bundleURL;
|
NSURL *_bundleURL;
|
||||||
RCTBridgeModuleProviderBlock _moduleProvider;
|
RCTBridgeModuleProviderBlock _moduleProvider;
|
||||||
|
RCTDisplayLink *_displayLink;
|
||||||
|
NSMutableSet *_frameUpdateObservers;
|
||||||
BOOL _loading;
|
BOOL _loading;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,6 +780,8 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||||
_latestJSExecutor = _javaScriptExecutor;
|
_latestJSExecutor = _javaScriptExecutor;
|
||||||
_eventDispatcher = [[RCTEventDispatcher alloc] initWithBridge:self];
|
_eventDispatcher = [[RCTEventDispatcher alloc] initWithBridge:self];
|
||||||
_shadowQueue = dispatch_queue_create("com.facebook.React.ShadowQueue", DISPATCH_QUEUE_SERIAL);
|
_shadowQueue = dispatch_queue_create("com.facebook.React.ShadowQueue", DISPATCH_QUEUE_SERIAL);
|
||||||
|
_displayLink = [[RCTDisplayLink alloc] initWithBridge:self];
|
||||||
|
_frameUpdateObservers = [[NSMutableSet alloc] init];
|
||||||
|
|
||||||
// Register passed-in module instances
|
// Register passed-in module instances
|
||||||
NSMutableDictionary *preregisteredModules = [[NSMutableDictionary alloc] init];
|
NSMutableDictionary *preregisteredModules = [[NSMutableDictionary alloc] init];
|
||||||
|
@ -891,6 +962,9 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||||
[_javaScriptExecutor invalidate];
|
[_javaScriptExecutor invalidate];
|
||||||
_javaScriptExecutor = nil;
|
_javaScriptExecutor = nil;
|
||||||
|
|
||||||
|
[_displayLink invalidate];
|
||||||
|
_frameUpdateObservers = nil;
|
||||||
|
|
||||||
// Invalidate modules
|
// Invalidate modules
|
||||||
for (id target in _modulesByID.allObjects) {
|
for (id target in _modulesByID.allObjects) {
|
||||||
if ([target respondsToSelector:@selector(invalidate)]) {
|
if ([target respondsToSelector:@selector(invalidate)]) {
|
||||||
|
@ -1075,6 +1149,26 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)_update:(CADisplayLink *)displayLink
|
||||||
|
{
|
||||||
|
RCTFrameUpdate *frameUpdate = [[RCTFrameUpdate alloc] initWithDisplayLink:displayLink];
|
||||||
|
for (id<RCTFrameUpdateObserver> observer in _frameUpdateObservers) {
|
||||||
|
if (![observer respondsToSelector:@selector(isPaused)] || ![observer isPaused]) {
|
||||||
|
[observer didUpdateFrame:frameUpdate];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)addFrameUpdateObserver:(id<RCTFrameUpdateObserver>)observer
|
||||||
|
{
|
||||||
|
[_frameUpdateObservers addObject:observer];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeFrameUpdateObserver:(id<RCTFrameUpdateObserver>)observer
|
||||||
|
{
|
||||||
|
[_frameUpdateObservers removeObject:observer];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)reload
|
- (void)reload
|
||||||
{
|
{
|
||||||
if (!_loading) {
|
if (!_loading) {
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface containing the information about the last screen refresh.
|
||||||
|
*/
|
||||||
|
@interface RCTFrameUpdate : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamp for the actual screen refresh
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly) NSTimeInterval timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time since the last frame update ( >= 16.6ms )
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly) NSTimeInterval deltaTime;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protocol that must be implemented for subscribing to display refreshes (DisplayLink updates)
|
||||||
|
*/
|
||||||
|
@protocol RCTFrameUpdateObserver <NSObject>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called on every screen refresh (if paused != YES)
|
||||||
|
*/
|
||||||
|
- (void)didUpdateFrame:(RCTFrameUpdate *)update;
|
||||||
|
|
||||||
|
@optional
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synthesize and set to true to pause the calls to -[didUpdateFrame:]
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign, getter=isPaused) BOOL paused;
|
||||||
|
|
||||||
|
@end
|
|
@ -10,8 +10,9 @@
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
#import "RCTBridgeModule.h"
|
#import "RCTBridgeModule.h"
|
||||||
|
#import "RCTFrameUpdate.h"
|
||||||
#import "RCTInvalidating.h"
|
#import "RCTInvalidating.h"
|
||||||
|
|
||||||
@interface RCTTiming : NSObject <RCTBridgeModule, RCTInvalidating>
|
@interface RCTTiming : NSObject <RCTBridgeModule, RCTInvalidating, RCTFrameUpdateObserver>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -58,7 +58,6 @@
|
||||||
@implementation RCTTiming
|
@implementation RCTTiming
|
||||||
{
|
{
|
||||||
RCTSparseArray *_timers;
|
RCTSparseArray *_timers;
|
||||||
id _updateTimer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@synthesize bridge = _bridge;
|
@synthesize bridge = _bridge;
|
||||||
|
@ -113,32 +112,21 @@ RCT_IMPORT_METHOD(RCTJSTimers, callTimers)
|
||||||
|
|
||||||
- (void)stopTimers
|
- (void)stopTimers
|
||||||
{
|
{
|
||||||
[_updateTimer invalidate];
|
[_bridge removeFrameUpdateObserver:self];
|
||||||
_updateTimer = nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)startTimers
|
- (void)startTimers
|
||||||
{
|
{
|
||||||
RCTAssertMainThread();
|
RCTAssertMainThread();
|
||||||
|
|
||||||
if (![self isValid] || _updateTimer != nil || _timers.count == 0) {
|
if (![self isValid] || _timers.count == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)];
|
[_bridge addFrameUpdateObserver:self];
|
||||||
if (_updateTimer) {
|
|
||||||
[_updateTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
|
|
||||||
} else {
|
|
||||||
RCTLogWarn(@"Failed to create a display link (probably on buildbot) - using an NSTimer for AppEngine instead.");
|
|
||||||
_updateTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60)
|
|
||||||
target:self
|
|
||||||
selector:@selector(update)
|
|
||||||
userInfo:nil
|
|
||||||
repeats:YES];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)update
|
- (void)didUpdateFrame:(RCTFrameUpdate *)update
|
||||||
{
|
{
|
||||||
RCTAssertMainThread();
|
RCTAssertMainThread();
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,7 @@
|
||||||
13E067541A70F44B002CDEE1 /* UIView+React.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+React.m"; sourceTree = "<group>"; };
|
13E067541A70F44B002CDEE1 /* UIView+React.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+React.m"; sourceTree = "<group>"; };
|
||||||
14200DA81AC179B3008EE6BA /* RCTJavaScriptLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJavaScriptLoader.h; sourceTree = "<group>"; };
|
14200DA81AC179B3008EE6BA /* RCTJavaScriptLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJavaScriptLoader.h; sourceTree = "<group>"; };
|
||||||
14200DA91AC179B3008EE6BA /* RCTJavaScriptLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTJavaScriptLoader.m; sourceTree = "<group>"; };
|
14200DA91AC179B3008EE6BA /* RCTJavaScriptLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTJavaScriptLoader.m; sourceTree = "<group>"; };
|
||||||
|
1436DD071ADE7AA000A5ED7D /* RCTFrameUpdate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTFrameUpdate.h; sourceTree = "<group>"; };
|
||||||
14435CE11AAC4AE100FC20F4 /* RCTMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMap.h; sourceTree = "<group>"; };
|
14435CE11AAC4AE100FC20F4 /* RCTMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMap.h; sourceTree = "<group>"; };
|
||||||
14435CE21AAC4AE100FC20F4 /* RCTMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMap.m; sourceTree = "<group>"; };
|
14435CE21AAC4AE100FC20F4 /* RCTMap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMap.m; sourceTree = "<group>"; };
|
||||||
14435CE31AAC4AE100FC20F4 /* RCTMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMapManager.h; sourceTree = "<group>"; };
|
14435CE31AAC4AE100FC20F4 /* RCTMapManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTMapManager.h; sourceTree = "<group>"; };
|
||||||
|
@ -391,6 +392,7 @@
|
||||||
83CBBA971A6020BB00E9B192 /* RCTTouchHandler.m */,
|
83CBBA971A6020BB00E9B192 /* RCTTouchHandler.m */,
|
||||||
83CBBA4F1A601E3B00E9B192 /* RCTUtils.h */,
|
83CBBA4F1A601E3B00E9B192 /* RCTUtils.h */,
|
||||||
83CBBA501A601E3B00E9B192 /* RCTUtils.m */,
|
83CBBA501A601E3B00E9B192 /* RCTUtils.m */,
|
||||||
|
1436DD071ADE7AA000A5ED7D /* RCTFrameUpdate.h */,
|
||||||
);
|
);
|
||||||
path = Base;
|
path = Base;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
|
@ -9,16 +9,17 @@
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "RCTFrameUpdate.h"
|
||||||
#import "RCTInvalidating.h"
|
#import "RCTInvalidating.h"
|
||||||
|
|
||||||
@class RCTEventDispatcher;
|
@class RCTBridge;
|
||||||
|
|
||||||
@interface RCTNavigator : UIView <RCTInvalidating>
|
@interface RCTNavigator : UIView <RCTFrameUpdateObserver>
|
||||||
|
|
||||||
@property (nonatomic, strong) UIView *reactNavSuperviewLink;
|
@property (nonatomic, strong) UIView *reactNavSuperviewLink;
|
||||||
@property (nonatomic, assign) NSInteger requestedTopOfStack;
|
@property (nonatomic, assign) NSInteger requestedTopOfStack;
|
||||||
|
|
||||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
|
- (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedules a JavaScript navigation and prevents `UIKit` from navigating until
|
* Schedules a JavaScript navigation and prevents `UIKit` from navigating until
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#import "RCTNavigator.h"
|
#import "RCTNavigator.h"
|
||||||
|
|
||||||
#import "RCTAssert.h"
|
#import "RCTAssert.h"
|
||||||
|
#import "RCTBridge.h"
|
||||||
#import "RCTConvert.h"
|
#import "RCTConvert.h"
|
||||||
#import "RCTEventDispatcher.h"
|
#import "RCTEventDispatcher.h"
|
||||||
#import "RCTLog.h"
|
#import "RCTLog.h"
|
||||||
|
@ -190,10 +191,6 @@ NSInteger kNeverProgressed = -10000;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface RCTNavigator() <RCTWrapperViewControllerNavigationListener, UINavigationControllerDelegate>
|
@interface RCTNavigator() <RCTWrapperViewControllerNavigationListener, UINavigationControllerDelegate>
|
||||||
{
|
|
||||||
RCTEventDispatcher *_eventDispatcher;
|
|
||||||
NSInteger _numberOfViewControllerMovesToIgnore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@property (nonatomic, assign) NSInteger previousRequestedTopOfStack;
|
@property (nonatomic, assign) NSInteger previousRequestedTopOfStack;
|
||||||
|
|
||||||
|
@ -251,7 +248,6 @@ NSInteger kNeverProgressed = -10000;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@property (nonatomic, readonly, assign) CGFloat mostRecentProgress;
|
@property (nonatomic, readonly, assign) CGFloat mostRecentProgress;
|
||||||
@property (nonatomic, readwrite, strong) CADisplayLink *displayLink;
|
|
||||||
@property (nonatomic, readonly, strong) NSTimer *runTimer;
|
@property (nonatomic, readonly, strong) NSTimer *runTimer;
|
||||||
@property (nonatomic, readonly, assign) NSInteger currentlyTransitioningFrom;
|
@property (nonatomic, readonly, assign) NSInteger currentlyTransitioningFrom;
|
||||||
@property (nonatomic, readonly, assign) NSInteger currentlyTransitioningTo;
|
@property (nonatomic, readonly, assign) NSInteger currentlyTransitioningTo;
|
||||||
|
@ -263,22 +259,17 @@ NSInteger kNeverProgressed = -10000;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation RCTNavigator
|
@implementation RCTNavigator
|
||||||
|
{
|
||||||
|
__weak RCTBridge *_bridge;
|
||||||
|
NSInteger _numberOfViewControllerMovesToIgnore;
|
||||||
|
}
|
||||||
|
|
||||||
- (id)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
- (id)initWithBridge:(RCTBridge *)bridge
|
||||||
{
|
{
|
||||||
if ((self = [super initWithFrame:CGRectZero])) {
|
if ((self = [super initWithFrame:CGRectZero])) {
|
||||||
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(reportNavigationProgress:)];
|
_bridge = bridge;
|
||||||
_mostRecentProgress = kNeverProgressed;
|
_mostRecentProgress = kNeverProgressed;
|
||||||
_dummyView = [[UIView alloc] initWithFrame:CGRectZero];
|
_dummyView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
if (_displayLink) {
|
|
||||||
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
|
|
||||||
_displayLink.paused = YES;
|
|
||||||
} else {
|
|
||||||
// It's okay to leak this on a build bot.
|
|
||||||
RCTLogWarn(@"Failed to create a display link (probably on automated build system) - using an NSTimer for AppEngine instead.");
|
|
||||||
_runTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60.0) target:self selector:@selector(reportNavigationProgress:) userInfo:nil repeats:YES];
|
|
||||||
}
|
|
||||||
_eventDispatcher = eventDispatcher;
|
|
||||||
_previousRequestedTopOfStack = kNeverRequested; // So that we initialize with a push.
|
_previousRequestedTopOfStack = kNeverRequested; // So that we initialize with a push.
|
||||||
_previousViews = @[];
|
_previousViews = @[];
|
||||||
_currentViews = [[NSMutableArray alloc] initWithCapacity:0];
|
_currentViews = [[NSMutableArray alloc] initWithCapacity:0];
|
||||||
|
@ -295,7 +286,7 @@ NSInteger kNeverProgressed = -10000;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)reportNavigationProgress:(CADisplayLink *)sender
|
- (void)didUpdateFrame:(RCTFrameUpdate *)update
|
||||||
{
|
{
|
||||||
if (_currentlyTransitioningFrom != _currentlyTransitioningTo) {
|
if (_currentlyTransitioningFrom != _currentlyTransitioningTo) {
|
||||||
UIView *topView = _dummyView;
|
UIView *topView = _dummyView;
|
||||||
|
@ -307,7 +298,7 @@ NSInteger kNeverProgressed = -10000;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_mostRecentProgress = nextProgress;
|
_mostRecentProgress = nextProgress;
|
||||||
[_eventDispatcher sendInputEventWithName:@"topNavigationProgress" body:@{
|
[_bridge.eventDispatcher sendInputEventWithName:@"topNavigationProgress" body:@{
|
||||||
@"fromIndex": @(_currentlyTransitioningFrom),
|
@"fromIndex": @(_currentlyTransitioningFrom),
|
||||||
@"toIndex": @(_currentlyTransitioningTo),
|
@"toIndex": @(_currentlyTransitioningTo),
|
||||||
@"progress": @(nextProgress),
|
@"progress": @(nextProgress),
|
||||||
|
@ -350,16 +341,14 @@ NSInteger kNeverProgressed = -10000;
|
||||||
_dummyView.frame = (CGRect){{destination}};
|
_dummyView.frame = (CGRect){{destination}};
|
||||||
_currentlyTransitioningFrom = indexOfFrom;
|
_currentlyTransitioningFrom = indexOfFrom;
|
||||||
_currentlyTransitioningTo = indexOfTo;
|
_currentlyTransitioningTo = indexOfTo;
|
||||||
if (indexOfFrom != indexOfTo) {
|
[_bridge addFrameUpdateObserver:self];
|
||||||
_displayLink.paused = NO;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
||||||
[weakSelf freeLock];
|
[weakSelf freeLock];
|
||||||
_currentlyTransitioningFrom = 0;
|
_currentlyTransitioningFrom = 0;
|
||||||
_currentlyTransitioningTo = 0;
|
_currentlyTransitioningTo = 0;
|
||||||
_dummyView.frame = CGRectZero;
|
_dummyView.frame = CGRectZero;
|
||||||
_displayLink.paused = YES;
|
[_bridge removeFrameUpdateObserver:self];
|
||||||
// Reset the parallel position tracker
|
// Reset the parallel position tracker
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
@ -400,19 +389,6 @@ NSInteger kNeverProgressed = -10000;
|
||||||
return _currentViews;
|
return _currentViews;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isValid
|
|
||||||
{
|
|
||||||
return _displayLink != nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)invalidate
|
|
||||||
{
|
|
||||||
// Prevent displayLink from retaining the navigator indefinitely
|
|
||||||
[_displayLink invalidate];
|
|
||||||
_displayLink = nil;
|
|
||||||
_runTimer = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)layoutSubviews
|
- (void)layoutSubviews
|
||||||
{
|
{
|
||||||
[super layoutSubviews];
|
[super layoutSubviews];
|
||||||
|
@ -430,7 +406,7 @@ NSInteger kNeverProgressed = -10000;
|
||||||
|
|
||||||
- (void)handleTopOfStackChanged
|
- (void)handleTopOfStackChanged
|
||||||
{
|
{
|
||||||
[_eventDispatcher sendInputEventWithName:@"topNavigateBack" body:@{
|
[_bridge.eventDispatcher sendInputEventWithName:@"topNavigateBack" body:@{
|
||||||
@"target":self.reactTag,
|
@"target":self.reactTag,
|
||||||
@"stackLength":@(_navigationController.viewControllers.count)
|
@"stackLength":@(_navigationController.viewControllers.count)
|
||||||
}];
|
}];
|
||||||
|
@ -438,7 +414,7 @@ NSInteger kNeverProgressed = -10000;
|
||||||
|
|
||||||
- (void)dispatchFakeScrollEvent
|
- (void)dispatchFakeScrollEvent
|
||||||
{
|
{
|
||||||
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeMove
|
[_bridge.eventDispatcher sendScrollEventWithType:RCTScrollEventTypeMove
|
||||||
reactTag:self.reactTag
|
reactTag:self.reactTag
|
||||||
scrollView:nil
|
scrollView:nil
|
||||||
userData:nil];
|
userData:nil];
|
||||||
|
@ -511,7 +487,7 @@ NSInteger kNeverProgressed = -10000;
|
||||||
if (jsGettingAhead) {
|
if (jsGettingAhead) {
|
||||||
if (reactPushOne) {
|
if (reactPushOne) {
|
||||||
UIView *lastView = [_currentViews lastObject];
|
UIView *lastView = [_currentViews lastObject];
|
||||||
RCTWrapperViewController *vc = [[RCTWrapperViewController alloc] initWithNavItem:(RCTNavItem *)lastView eventDispatcher:_eventDispatcher];
|
RCTWrapperViewController *vc = [[RCTWrapperViewController alloc] initWithNavItem:(RCTNavItem *)lastView eventDispatcher:_bridge.eventDispatcher];
|
||||||
vc.navigationListener = self;
|
vc.navigationListener = self;
|
||||||
_numberOfViewControllerMovesToIgnore = 1;
|
_numberOfViewControllerMovesToIgnore = 1;
|
||||||
[_navigationController pushViewController:vc animated:(currentReactCount > 1)];
|
[_navigationController pushViewController:vc animated:(currentReactCount > 1)];
|
||||||
|
|
|
@ -21,7 +21,7 @@ RCT_EXPORT_MODULE()
|
||||||
|
|
||||||
- (UIView *)view
|
- (UIView *)view
|
||||||
{
|
{
|
||||||
return [[RCTNavigator alloc] initWithEventDispatcher:self.bridge.eventDispatcher];
|
return [[RCTNavigator alloc] initWithBridge:self.bridge];
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(requestedTopOfStack, NSInteger)
|
RCT_EXPORT_VIEW_PROPERTY(requestedTopOfStack, NSInteger)
|
||||||
|
|
Loading…
Reference in New Issue