react-native/React/Base/RCTKeyboardObserver.m
Nick Lockwood e72163f0f2 Added explicit init to observer modules
Summary:
Modules which call JS methods directly, or use `sendDeviceEventWithName:`, can trigger effects in JS without ever being referenced from the JS code. This breaks some assumptions in my earlier diff about when modules can be lazily loaded.

Pending a better solution, I've put explicit `init` methods in these modules to ensure they are eagerly initialized (the downside to this is that they'll still be initialized even if they are never used).

Reviewed By: javache

Differential Revision: D3258232

fb-gh-sync-id: f925bc2e5339c1fbfcc244d4613062c5ab848fc2
fbshipit-source-id: f925bc2e5339c1fbfcc244d4613062c5ab848fc2
2016-05-04 07:07:24 -07:00

112 lines
3.3 KiB
Objective-C

/**
* 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.
*/
#import "RCTKeyboardObserver.h"
#import "RCTEventDispatcher.h"
static NSDictionary *RCTParseKeyboardNotification(NSNotification *notification);
@implementation RCTKeyboardObserver
@synthesize bridge = _bridge;
RCT_EXPORT_MODULE()
- (instancetype)init
{
// We're only overriding this to ensure the module gets created at startup
// TODO (t11106126): Remove once we have more declarative control over module setup.
return [super init];
}
- (void)setBridge:(RCTBridge *)bridge
{
_bridge = bridge;
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
#define ADD_KEYBOARD_HANDLER(NAME, SELECTOR) \
[nc addObserver:self selector:@selector(SELECTOR:) name:NAME object:nil]
ADD_KEYBOARD_HANDLER(UIKeyboardWillShowNotification, keyboardWillShow);
ADD_KEYBOARD_HANDLER(UIKeyboardDidShowNotification, keyboardDidShow);
ADD_KEYBOARD_HANDLER(UIKeyboardWillHideNotification, keyboardWillHide);
ADD_KEYBOARD_HANDLER(UIKeyboardDidHideNotification, keyboardDidHide);
ADD_KEYBOARD_HANDLER(UIKeyboardWillChangeFrameNotification, keyboardWillChangeFrame);
ADD_KEYBOARD_HANDLER(UIKeyboardDidChangeFrameNotification, keyboardDidChangeFrame);
#undef ADD_KEYBOARD_HANDLER
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#define IMPLEMENT_KEYBOARD_HANDLER(EVENT) \
- (void)EVENT:(NSNotification *)notification \
{ \
[_bridge.eventDispatcher \
sendDeviceEventWithName:@#EVENT \
body:RCTParseKeyboardNotification(notification)]; \
}
IMPLEMENT_KEYBOARD_HANDLER(keyboardWillShow)
IMPLEMENT_KEYBOARD_HANDLER(keyboardDidShow)
IMPLEMENT_KEYBOARD_HANDLER(keyboardWillHide)
IMPLEMENT_KEYBOARD_HANDLER(keyboardDidHide)
IMPLEMENT_KEYBOARD_HANDLER(keyboardWillChangeFrame)
IMPLEMENT_KEYBOARD_HANDLER(keyboardDidChangeFrame)
@end
NS_INLINE NSDictionary *RCTRectDictionaryValue(CGRect rect)
{
return @{
@"screenX": @(rect.origin.x),
@"screenY": @(rect.origin.y),
@"width": @(rect.size.width),
@"height": @(rect.size.height),
};
}
static NSString *RCTAnimationNameForCurve(UIViewAnimationCurve curve)
{
switch (curve) {
case UIViewAnimationCurveEaseIn:
return @"easeIn";
case UIViewAnimationCurveEaseInOut:
return @"easeInEaseOut";
case UIViewAnimationCurveEaseOut:
return @"easeOut";
case UIViewAnimationCurveLinear:
return @"linear";
default:
return @"keyboard";
}
}
static NSDictionary *RCTParseKeyboardNotification(NSNotification *notification)
{
NSDictionary *userInfo = notification.userInfo;
CGRect beginFrame = [userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
return @{
@"startCoordinates": RCTRectDictionaryValue(beginFrame),
@"endCoordinates": RCTRectDictionaryValue(endFrame),
@"duration": @(duration * 1000.0), // ms
@"easing": RCTAnimationNameForCurve(curve),
};
}