Files
react-native-reanimated/ios/REAModule.m
Michał Osadnik 3bbf8a0fed Make Animated Value persist its value after reattaching (#87)
When value gets detached from all component it can be still kept in memory and attached to some other component at later time. But because we don't know when JS reference is dropped we need to delete native counterpart of the value when it gets detached. This has led to a situation in which the value was reinstantiated on the native site. In that case if the value has changed we expect it to persist that changes when it gets attached again. This wasn't happening and each time the value was instantiated we'd always use the initial value.

With this change we are solving that issue by querying the value right before we detach the native node and then we use that value to update config such that next time when it gets instantiated it uses updated value instead of the initial one.
2018-09-28 13:45:51 +02:00

168 lines
4.8 KiB
Objective-C

#import "REAModule.h"
#import "REANodesManager.h"
typedef void (^AnimatedOperation)(REANodesManager *nodesManager);
@implementation REAModule
{
REANodesManager *_nodesManager;
NSMutableArray<AnimatedOperation> *_operations;
}
RCT_EXPORT_MODULE(ReanimatedModule);
- (void)invalidate
{
[_nodesManager invalidate];
[self.bridge.eventDispatcher removeDispatchObserver:self];
[self.bridge.uiManager.observerCoordinator removeObserver:self];
}
- (dispatch_queue_t)methodQueue
{
// This module needs to be on the same queue as the UIManager to avoid
// having to lock `_operations` and `_preOperations` since `uiManagerWillPerformMounting`
// will be called from that queue.
return RCTGetUIManagerQueue();
}
- (void)setBridge:(RCTBridge *)bridge
{
[super setBridge:bridge];
_nodesManager = [[REANodesManager alloc] initWithModule:self
uiManager:self.bridge.uiManager];
_operations = [NSMutableArray new];
[bridge.eventDispatcher addDispatchObserver:self];
[bridge.uiManager.observerCoordinator addObserver:self];
}
#pragma mark -- API
RCT_EXPORT_METHOD(createNode:(nonnull NSNumber *)nodeID
config:(NSDictionary<NSString *, id> *)config)
{
[self addOperationBlock:^(REANodesManager *nodesManager) {
[nodesManager createNode:nodeID config:config];
}];
}
RCT_EXPORT_METHOD(dropNode:(nonnull NSNumber *)nodeID)
{
[self addOperationBlock:^(REANodesManager *nodesManager) {
[nodesManager dropNode:nodeID];
}];
}
RCT_EXPORT_METHOD(getValue:(nonnull NSNumber *)nodeID
callback:(RCTResponseSenderBlock)callback) {
[self addOperationBlock:^(REANodesManager *nodesManager) {
[nodesManager getValue:nodeID callback:(RCTResponseSenderBlock)callback];
}];
}
RCT_EXPORT_METHOD(connectNodes:(nonnull NSNumber *)parentID
childTag:(nonnull NSNumber *)childID)
{
[self addOperationBlock:^(REANodesManager *nodesManager) {
[nodesManager connectNodes:parentID childID:childID];
}];
}
RCT_EXPORT_METHOD(disconnectNodes:(nonnull NSNumber *)parentID
childTag:(nonnull NSNumber *)childID)
{
[self addOperationBlock:^(REANodesManager *nodesManager) {
[nodesManager disconnectNodes:parentID childID:childID];
}];
}
RCT_EXPORT_METHOD(connectNodeToView:(nonnull NSNumber *)nodeID
viewTag:(nonnull NSNumber *)viewTag)
{
NSString *viewName = [self.bridge.uiManager viewNameForReactTag:viewTag];
[self addOperationBlock:^(REANodesManager *nodesManager) {
[nodesManager connectNodeToView:nodeID viewTag:viewTag viewName:viewName];
}];
}
RCT_EXPORT_METHOD(disconnectNodeFromView:(nonnull NSNumber *)nodeID
viewTag:(nonnull NSNumber *)viewTag)
{
[self addOperationBlock:^(REANodesManager *nodesManager) {
[nodesManager disconnectNodeFromView:nodeID viewTag:viewTag];
}];
}
RCT_EXPORT_METHOD(attachEvent:(nonnull NSNumber *)viewTag
eventName:(nonnull NSString *)eventName
eventNodeID:(nonnull NSNumber *)eventNodeID)
{
[self addOperationBlock:^(REANodesManager *nodesManager) {
[nodesManager attachEvent:viewTag eventName:eventName eventNodeID:eventNodeID];
}];
}
RCT_EXPORT_METHOD(detachEvent:(nonnull NSNumber *)viewTag
eventName:(nonnull NSString *)eventName
eventNodeID:(nonnull NSNumber *)eventNodeID)
{
[self addOperationBlock:^(REANodesManager *nodesManager) {
[nodesManager detachEvent:viewTag eventName:eventName eventNodeID:eventNodeID];
}];
}
RCT_EXPORT_METHOD(configureProps:(nonnull NSArray<NSString *> *)nativeProps
uiProps:(nonnull NSArray<NSString *> *)uiProps)
{
[self addOperationBlock:^(REANodesManager *nodesManager) {
[nodesManager configureProps:[NSSet setWithArray:nativeProps] uiProps:[NSSet setWithArray:uiProps]];
}];
}
#pragma mark -- Batch handling
- (void)addOperationBlock:(AnimatedOperation)operation
{
[_operations addObject:operation];
}
#pragma mark - RCTUIManagerObserver
- (void)uiManagerWillPerformMounting:(RCTUIManager *)uiManager
{
if (_operations.count == 0) {
return;
}
NSArray<AnimatedOperation> *operations = _operations;
_operations = [NSMutableArray new];
REANodesManager *nodesManager = _nodesManager;
[uiManager addUIBlock:^(__unused RCTUIManager *manager, __unused NSDictionary<NSNumber *, UIView *> *viewRegistry) {
for (AnimatedOperation operation in operations) {
operation(nodesManager);
}
[nodesManager operationsBatchDidComplete];
}];
}
#pragma mark -- Events
- (NSArray<NSString *> *)supportedEvents
{
return @[@"onReanimatedCall", @"onReanimatedPropsChange"];
}
- (void)eventDispatcherWillDispatchEvent:(id<RCTEvent>)event
{
// Events can be dispatched from any queue
[_nodesManager dispatchEvent:event];
}
@end