2015-02-30 update:

- [ReactNative] Fix indentation | Ben Alpert
- [ReactKit] Bring back ability to jump to syntax error from redbox | Alex Kotliarskyi
- [ReactKit] Update pthread.h import path to be (more?) correct | Ben Alpert
- Simplified event handling | Nick Lockwood
- [ReactNative] more readme - xcode error help | Spencer Ahrens
This commit is contained in:
Christopher Chedeau
2015-02-03 16:02:36 -08:00
parent 0512e23ba9
commit 00f0ebccdf
46 changed files with 596 additions and 1191 deletions

View File

@@ -7,7 +7,7 @@
@implementation RCTNavItemManager
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
return [[RCTNavItem alloc] initWithFrame:CGRectZero];
}

View File

@@ -2,7 +2,7 @@
#import <UIKit/UIKit.h>
@class RCTJavaScriptEventDispatcher;
@class RCTEventDispatcher;
@interface RCTNavigator : UIView <UINavigationControllerDelegate>
@@ -10,7 +10,7 @@
@property (nonatomic, assign) NSInteger requestedTopOfStack;
- (instancetype)initWithFrame:(CGRect)frame
eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher;
eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
/**
* Schedules a JavaScript navigation and prevents `UIKit` from navigating until

View File

@@ -4,8 +4,7 @@
#import "RCTAssert.h"
#import "RCTConvert.h"
#import "RCTEventExtractor.h"
#import "RCTJavaScriptEventDispatcher.h"
#import "RCTEventDispatcher.h"
#import "RCTLog.h"
#import "RCTNavItem.h"
#import "RCTUtils.h"
@@ -138,7 +137,7 @@ NSInteger kNeverProgressed = -10000;
*/
- (instancetype)initWithScrollCallback:(dispatch_block_t)callback
{
if (self = [super init]) {
if ((self = [super init])) {
_scrollCallback = callback;
}
return self;
@@ -193,7 +192,7 @@ NSInteger kNeverProgressed = -10000;
@interface RCTNavigator() <RCTWrapperViewControllerNavigationListener>
{
RCTJavaScriptEventDispatcher *_eventDispatcher;
RCTEventDispatcher *_eventDispatcher;
NSInteger _numberOfViewControllerMovesToIgnore;
}
@@ -267,7 +266,7 @@ NSInteger kNeverProgressed = -10000;
@implementation RCTNavigator
- (id)initWithFrame:(CGRect)frame
eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
eventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
self = [super initWithFrame:frame];
if (self) {
@@ -311,16 +310,12 @@ NSInteger kNeverProgressed = -10000;
if (nextProgress == _mostRecentProgress) {
return;
}
NSDictionary *nativeEventObj = @{
@"fromIndex": @(_currentlyTransitioningFrom),
@"toIndex": @(_currentlyTransitioningTo),
@"progress": @(nextProgress),
@"target": self.reactTag ?: @0,
};
_mostRecentProgress = nextProgress;
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:self.reactTag
type:RCTEventNavigationProgress
nativeEventObj:nativeEventObj]];
[_eventDispatcher sendRawEventWithType:@"topNavigationProgress"
body:@{@"fromIndex": @(_currentlyTransitioningFrom),
@"toIndex": @(_currentlyTransitioningTo),
@"progress": @(nextProgress),
@"target": self.reactTag}];
}
}
@@ -443,21 +438,17 @@ NSInteger kNeverProgressed = -10000;
- (void)handleTopOfStackChanged
{
NSDictionary *nativeEventObj = @{
@"target":self.reactTag ?: @0,
@"stackLength":@(_navigationController.viewControllers.count)
};
NSArray *eventArgs = [RCTEventExtractor eventArgs:self.reactTag
type:RCTEventNavigateBack
nativeEventObj:nativeEventObj];
[_eventDispatcher sendEventWithArgs:eventArgs];
[_eventDispatcher sendRawEventWithType:@"topNavigateBack"
body:@{@"target":self.reactTag,
@"stackLength":@(_navigationController.viewControllers.count)}];
}
- (void)dispatchFakeScrollEvent
{
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[self reactTag]
type:RCTEventScroll
nativeEventObj:[RCTEventExtractor fakeScrollEventObjectFor:[self reactTag]]]];
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeMove
reactTag:self.reactTag
scrollView:nil
userData:nil];
}
/**

View File

@@ -8,7 +8,7 @@
@implementation RCTNavigatorManager
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
return [[RCTNavigator alloc] initWithFrame:CGRectZero eventDispatcher:eventDispatcher];
}

View File

@@ -11,7 +11,7 @@
@implementation RCTNetworkImageViewManager
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
RCTNetworkImageView *view = [[RCTNetworkImageView alloc] initWithFrame:CGRectZero imageDownloader:[RCTImageDownloader sharedInstance]];
view.contentMode = UIViewContentModeScaleAspectFill;

View File

@@ -6,7 +6,7 @@
@implementation RCTRawTextManager
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
return [[UIView alloc] init];
}

View File

@@ -8,7 +8,7 @@
@protocol UIScrollViewDelegate;
@class RCTJavaScriptEventDispatcher;
@class RCTEventDispatcher;
@interface RCTScrollView : RCTView <UIScrollViewDelegate, RCTScrollableProtocol, RCTAutoInsetsProtocol>
@@ -32,6 +32,6 @@
@property (nonatomic, assign) BOOL centerContent;
@property (nonatomic, copy) NSArray *stickyHeaderIndices;
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher;
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
@end

View File

@@ -5,10 +5,8 @@
#import <UIKit/UIKit.h>
#import "RCTConvert.h"
#import "RCTEventExtractor.h"
#import "RCTJavaScriptEventDispatcher.h"
#import "RCTEventDispatcher.h"
#import "RCTLog.h"
#import "RCTScrollDispatcher.h"
#import "RCTUIManager.h"
#import "UIView+ReactKit.h"
@@ -249,24 +247,20 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
@end
@interface RCTScrollView ()
@implementation RCTScrollView
{
RCTJavaScriptEventDispatcher *_eventDispatcher;
RCTEventDispatcher *_eventDispatcher;
BOOL _contentSizeManuallySet;
RCTScrollDispatcher *_scrollDispatcher;
RCTCustomScrollView *_scrollView;
UIView *_contentView;
NSTimeInterval _lastScrollDispatchTime;
NSMutableArray *_cachedChildFrames;
BOOL _allowNextScrollNoMatterWhat;
}
@property (nonatomic, readwrite, assign) BOOL didThrottleMomentumScrollEvent;
@end
@implementation RCTScrollView
@synthesize nativeMainScrollDelegate = _nativeMainScrollDelegate;
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
if ((self = [super initWithFrame:frame])) {
@@ -274,9 +268,12 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
_scrollView = [[RCTCustomScrollView alloc] initWithFrame:CGRectZero];
_scrollView.delegate = self;
_scrollView.delaysContentTouches = NO;
_scrollDispatcher = [[RCTScrollDispatcher alloc] initWithEventDispatcher:eventDispatcher];
_automaticallyAdjustContentInsets = YES;
_contentInset = UIEdgeInsetsZero;
_throttleScrollCallbackMS = 0;
_lastScrollDispatchTime = CACurrentMediaTime();
_cachedChildFrames = [[NSMutableArray alloc] init];
[self addSubview:_scrollView];
}
@@ -371,90 +368,120 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
[_scrollView zoomToRect:rect animated:animated];
}
#pragma mark - UIScrollViewDelegate methods
#pragma mark - ScrollView delegate
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[_scrollDispatcher scrollViewDidEndScrollingAnimation:_scrollView reactTag:[self reactTag]];
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewDidEndScrollingAnimation:)]) {
[_nativeMainScrollDelegate scrollViewDidEndScrollingAnimation:scrollView];
}
#define RCT_SCROLL_EVENT_HANDLER(delegateMethod, eventName) \
- (void)delegateMethod:(UIScrollView *)scrollView \
{ \
[_eventDispatcher sendScrollEventWithType:eventName reactTag:self.reactTag scrollView:scrollView userData:nil]; \
if ([_nativeMainScrollDelegate respondsToSelector:_cmd]) { \
[_nativeMainScrollDelegate delegateMethod:scrollView]; \
} \
}
#define RCT_FORWARD_SCROLL_EVENT(call) \
if ([_nativeMainScrollDelegate respondsToSelector:_cmd]) { \
[_nativeMainScrollDelegate call]; \
}
RCT_SCROLL_EVENT_HANDLER(scrollViewDidEndScrollingAnimation, RCTScrollEventTypeEndDeceleration)
RCT_SCROLL_EVENT_HANDLER(scrollViewWillBeginDecelerating, RCTScrollEventTypeStartDeceleration)
RCT_SCROLL_EVENT_HANDLER(scrollViewDidEndDecelerating, RCTScrollEventTypeEndDeceleration)
RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, RCTScrollEventTypeMove)
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[_scrollDispatcher scrollViewDidScroll:_scrollView reactTag:[self reactTag]];
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) {
[_nativeMainScrollDelegate scrollViewDidScroll:scrollView];
}
}
NSTimeInterval now = CACurrentMediaTime();
NSTimeInterval throttleScrollCallbackSeconds = _throttleScrollCallbackMS / 1000.0;
/**
* TODO: this logic looks wrong, and it may be because it is. Currently, if _throttleScrollCallbackMS
* is set to zero (the default), the "didScroll" event is only sent once per scroll, instead of repeatedly
* while scrolling as expected. However, if you "fix" that bug, ScrollView will generate repeated
* warnings, and behave strangely (ListView works fine however), so don't fix it unless you fix that too!
*/
if (_allowNextScrollNoMatterWhat ||
(_throttleScrollCallbackMS != 0 && throttleScrollCallbackSeconds < (now - _lastScrollDispatchTime))) {
// Calculate changed frames
NSMutableArray *updatedChildFrames = [[NSMutableArray alloc] init];
[[_contentView reactSubviews] enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) {
// Check if new or changed
CGRect newFrame = subview.frame;
BOOL frameChanged = NO;
if (_cachedChildFrames.count <= idx) {
frameChanged = YES;
[_cachedChildFrames addObject:[NSValue valueWithCGRect:newFrame]];
} else if (!CGRectEqualToRect(newFrame, [_cachedChildFrames[idx] CGRectValue])) {
frameChanged = YES;
_cachedChildFrames[idx] = [NSValue valueWithCGRect:newFrame];
}
// Create JS frame object
if (frameChanged) {
[updatedChildFrames addObject: @{
@"index": @(idx),
@"x": @(newFrame.origin.x),
@"y": @(newFrame.origin.y),
@"width": @(newFrame.size.width),
@"height": @(newFrame.size.height),
}];
}
}];
// If there are new frames, add them to event data
NSDictionary *userData = nil;
if (updatedChildFrames.count > 0) {
userData = @{@"updatedChildFrames": updatedChildFrames};
}
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
[_scrollDispatcher scrollViewWillBeginDecelerating:_scrollView reactTag:[self reactTag]];
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewWillBeginDecelerating:)]) {
[_nativeMainScrollDelegate scrollViewWillBeginDecelerating:scrollView];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[_scrollDispatcher scrollViewDidEndDecelerating:_scrollView reactTag:[self reactTag]];
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) {
[_nativeMainScrollDelegate scrollViewDidEndDecelerating:scrollView];
// Dispatch event
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeMove
reactTag:self.reactTag
scrollView:scrollView
userData:userData];
// Update dispatch time
_lastScrollDispatchTime = now;
_allowNextScrollNoMatterWhat = NO;
}
RCT_FORWARD_SCROLL_EVENT(scrollViewDidScroll:scrollView);
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) {
[_nativeMainScrollDelegate scrollViewWillBeginDragging:scrollView];
}
[_scrollDispatcher scrollViewWillBeginDragging:_scrollView reactTag:[self reactTag]];
_allowNextScrollNoMatterWhat = YES; // Ensure next scroll event is recorded, regardless of throttle
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeStart reactTag:self.reactTag scrollView:scrollView userData:nil];
RCT_FORWARD_SCROLL_EVENT(scrollViewWillBeginDragging:scrollView);
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
[_scrollDispatcher scrollViewWillEndDragging:_scrollView reactTag:[self reactTag]];
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) {
[_nativeMainScrollDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset];
}
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeEnd reactTag:self.reactTag scrollView:scrollView userData:nil];
RCT_FORWARD_SCROLL_EVENT(scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset);
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) {
[_nativeMainScrollDelegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
}
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
[_scrollDispatcher scrollViewDidScroll:_scrollView reactTag:[self reactTag]];
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewDidZoom:)]) {
[_nativeMainScrollDelegate scrollViewDidZoom:scrollView];
}
RCT_FORWARD_SCROLL_EVENT(scrollViewDidEndDragging:scrollView willDecelerate:decelerate);
}
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
{
[_scrollDispatcher scrollViewWillBeginDragging:_scrollView reactTag:[self reactTag]];
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewWillBeginZooming:withView:)]) {
[_nativeMainScrollDelegate scrollViewWillBeginZooming:scrollView withView:view];
}
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeStart reactTag:self.reactTag scrollView:scrollView userData:nil];
RCT_FORWARD_SCROLL_EVENT(scrollViewWillBeginZooming:scrollView withView:view);
}
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
{
[_scrollDispatcher scrollViewWillEndDragging:_scrollView reactTag:[self reactTag]];
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewDidEndZooming:withView:atScale:)]) {
[_nativeMainScrollDelegate scrollViewDidEndZooming:scrollView withView:view atScale:scale];
}
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeEnd reactTag:self.reactTag scrollView:scrollView userData:nil];
RCT_FORWARD_SCROLL_EVENT(scrollViewDidEndZooming:scrollView withView:view atScale:scale);
}
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
{
if ([_nativeMainScrollDelegate respondsToSelector:@selector(scrollViewShouldScrollToTop:)]) {
if ([_nativeMainScrollDelegate respondsToSelector:_cmd]) {
return [_nativeMainScrollDelegate scrollViewShouldScrollToTop:scrollView];
}
return YES;
@@ -467,11 +494,6 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
#pragma mark - Setters
- (void)setThrottleScrollCallbackMS:(NSUInteger)ms
{
_scrollDispatcher.throttleScrollCallbackMS = ms;
}
- (CGSize)_calculateViewportSize
{
CGSize viewportSize = self.bounds.size;
@@ -527,27 +549,24 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
{
if (_contentSizeManuallySet) {
_scrollView.contentSize = _contentSize;
} else if (!_contentView) {
_scrollView.contentSize = CGSizeZero;
} else {
if (!_contentView) {
_scrollView.contentSize = CGSizeZero;
} else {
CGSize singleSubviewSize = _contentView.frame.size;
CGPoint singleSubviewPosition = _contentView.frame.origin;
CGSize fittedSize = CGSizeMake(
singleSubviewSize.width + singleSubviewPosition.x,
singleSubviewSize.height + singleSubviewPosition.y
);
if (!CGSizeEqualToSize(_scrollView.contentSize, fittedSize)) {
// When contentSize is set manually, ScrollView internals will reset contentOffset to 0,0. Since
// we potentially set contentSize whenever anything in the ScrollView updates, we workaround this
// issue by manually adjusting contentOffset whenever this happens
CGPoint newOffset = [self calculateOffsetForContentSize:fittedSize];
_scrollView.contentSize = fittedSize;
_scrollView.contentOffset = newOffset;
}
// when react makes changes to our
[_scrollView dockClosestSectionHeader];
CGSize singleSubviewSize = _contentView.frame.size;
CGPoint singleSubviewPosition = _contentView.frame.origin;
CGSize fittedSize = {
singleSubviewSize.width + singleSubviewPosition.x,
singleSubviewSize.height + singleSubviewPosition.y
};
if (!CGSizeEqualToSize(_scrollView.contentSize, fittedSize)) {
// When contentSize is set manually, ScrollView internals will reset contentOffset to 0,0. Since
// we potentially set contentSize whenever anything in the ScrollView updates, we workaround this
// issue by manually adjusting contentOffset whenever this happens
CGPoint newOffset = [self calculateOffsetForContentSize:fittedSize];
_scrollView.contentSize = fittedSize;
_scrollView.contentOffset = newOffset;
}
[_scrollView dockClosestSectionHeader];
}
}

View File

@@ -7,7 +7,7 @@
@implementation RCTScrollViewManager
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
return [[RCTScrollView alloc] initWithFrame:CGRectZero eventDispatcher:eventDispatcher];
}
@@ -33,8 +33,8 @@ RCT_EXPORT_VIEW_PROPERTY(stickyHeaderIndices);
RCT_EXPORT_VIEW_PROPERTY(throttleScrollCallbackMS);
RCT_EXPORT_VIEW_PROPERTY(zoomScale);
RCT_EXPORT_VIEW_PROPERTY(contentInset);
RCT_REMAP_VIEW_PROPERTY(scrollIndicatorInsets, scrollView.scrollIndicatorInsets);
RCT_REMAP_VIEW_PROPERTY(contentOffset, scrollView.contentOffse);
RCT_EXPORT_VIEW_PROPERTY(scrollIndicatorInsets);
RCT_EXPORT_VIEW_PROPERTY(contentOffset);
- (NSDictionary *)constantsToExport
{

View File

@@ -183,17 +183,17 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
node->layout.should_update = false;
_layoutLifecycle = RCTLayoutLifecycleComputed;
CGPoint absoluteTopLeft = (CGPoint){
CGPoint absoluteTopLeft = {
RCTRoundPixelValue(absolutePosition.x + node->layout.position[CSS_LEFT]),
RCTRoundPixelValue(absolutePosition.y + node->layout.position[CSS_TOP])
};
CGPoint absoluteBottomRight = (CGPoint){
CGPoint absoluteBottomRight = {
RCTRoundPixelValue(absolutePosition.x + node->layout.position[CSS_LEFT] + node->layout.dimensions[CSS_WIDTH]),
RCTRoundPixelValue(absolutePosition.y + node->layout.position[CSS_TOP] + node->layout.dimensions[CSS_HEIGHT])
};
CGRect frame = (CGRect){
CGRect frame = {
RCTRoundPixelValue(node->layout.position[CSS_LEFT]),
RCTRoundPixelValue(node->layout.position[CSS_TOP]),
RCTRoundPixelValue(absoluteBottomRight.x - absoluteTopLeft.x),

View File

@@ -9,7 +9,7 @@
@implementation RCTStaticImageManager
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
return [[RCTStaticImage alloc] init];
}

View File

@@ -2,7 +2,7 @@
#import <UIKit/UIKit.h>
@class RCTJavaScriptEventDispatcher;
@class RCTEventDispatcher;
@interface RCTTextField : UITextField
@@ -10,6 +10,6 @@
@property (nonatomic, assign) BOOL autoCorrect;
@property (nonatomic, assign) UIEdgeInsets paddingEdgeInsets; // TODO: contentInset
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher;
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
@end

View File

@@ -3,14 +3,13 @@
#import "RCTTextField.h"
#import "RCTConvert.h"
#import "RCTEventExtractor.h"
#import "RCTJavaScriptEventDispatcher.h"
#import "RCTEventDispatcher.h"
#import "RCTUtils.h"
#import "UIView+ReactKit.h"
@implementation RCTTextField
{
RCTJavaScriptEventDispatcher *_eventDispatcher;
RCTEventDispatcher *_eventDispatcher;
NSMutableArray *_reactSubviews;
BOOL _jsRequestingFirstResponder;
}
@@ -20,33 +19,41 @@
RCT_NOT_DESIGNATED_INITIALIZER();
}
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
if (self = [super initWithFrame:frame]) {
if ((self = [super initWithFrame:frame])) {
_eventDispatcher = eventDispatcher;
[self addTarget:self action:@selector(_textFieldDidChange) forControlEvents:UIControlEventEditingChanged];
[self addTarget:self action:@selector(_textFieldBeginEditing) forControlEvents:UIControlEventEditingDidBegin];
[self addTarget:self action:@selector(_textFieldEndEditing) forControlEvents:UIControlEventEditingDidEnd];
[self addTarget:self action:@selector(_textFieldSubmitEditing) forControlEvents:UIControlEventEditingDidEndOnExit];
_reactSubviews = [[NSMutableArray alloc] init];
self.returnKeyType = UIReturnKeyDone;
}
return self;
}
- (NSArray *)reactSubviews
{
// TODO: do we support subviews of textfield in React?
// In any case, we should have a better approach than manually
// maintaining array in each view subclass like this
return _reactSubviews;
}
- (void)removeReactSubview:(UIView *)subview
{
// TODO: this is a bit broken - if the TextView inserts any of
// it's own views below or between React's, the indices won't match
[_reactSubviews removeObject:subview];
[subview removeFromSuperview];
}
- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex
{
// TODO: this is a bit broken - if the TextView inserts any of
// it's own views below or between React's, the indices won't match
[_reactSubviews insertObject:view atIndex:atIndex];
[super insertSubview:view atIndex:atIndex];
}
@@ -56,7 +63,6 @@
if (_caretHidden) {
return CGRectZero;
}
return [super caretRectForPosition:position];
}
@@ -81,72 +87,45 @@
return self.autocorrectionType == UITextAutocorrectionTypeYes;
}
- (void)_textFieldDidChange
{
[self handleTextChange];
#define RCT_TEXT_EVENT_HANDLER(delegateMethod, eventName) \
- (void)delegateMethod \
{ \
[_eventDispatcher sendTextEventWithType:eventName \
reactTag:self.reactTag \
text:self.text]; \
}
- (void)_textFieldEndEditing
{
NSDictionary *event = @{@"text": self.text, @"target": self.reactTag};
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[self reactTag]
type:RCTEventTextFieldEndEditing
nativeEventObj:event]];
}
RCT_TEXT_EVENT_HANDLER(_textFieldDidChange, RCTTextEventTypeChange)
RCT_TEXT_EVENT_HANDLER(_textFieldBeginEditing, RCTTextEventTypeFocus)
RCT_TEXT_EVENT_HANDLER(_textFieldEndEditing, RCTTextEventTypeEnd)
RCT_TEXT_EVENT_HANDLER(_textFieldSubmitEditing, RCTTextEventTypeSubmit)
- (void)_textFieldSubmitEditing
{
NSDictionary *event = @{@"text": self.text, @"target": self.reactTag};
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[self reactTag]
type:RCTEventTextFieldSubmitEditing
nativeEventObj:event]];
}
// TODO: we should support shouldChangeTextInRect (see UITextFieldDelegate)
- (BOOL)becomeFirstResponder
{
_jsRequestingFirstResponder = YES;
BOOL wasPreviouslyResponder = [self isFirstResponder];
BOOL ret = [super becomeFirstResponder];
BOOL isTransitioningResponder = !wasPreviouslyResponder && ret;
if (isTransitioningResponder) {
[self handleTextFieldDidFocus];
}
_jsRequestingFirstResponder = YES; // TODO: is this still needed?
BOOL result = [super becomeFirstResponder];
_jsRequestingFirstResponder = NO;
return ret;
return result;
}
- (BOOL)resignFirstResponder
{
[self handleTextFieldWillBlur];
return [super resignFirstResponder];
BOOL result = [super resignFirstResponder];
if (result)
{
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeBlur
reactTag:self.reactTag
text:self.text];
}
return result;
}
// Prevent native from becoming first responder
// Prevent native from becoming first responder (TODO: why?)
- (BOOL)canBecomeFirstResponder
{
return _jsRequestingFirstResponder;
}
- (void)handleTextChange
{
NSDictionary *event = @{@"text": self.text, @"target": self.reactTag};
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[self reactTag]
type:RCTEventChange
nativeEventObj:event]];
}
- (void)handleTextFieldDidFocus
{
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[self reactTag]
type:RCTEventTextFieldDidFocus
nativeEventObj:@{@"target":self.reactTag}]];
}
- (void)handleTextFieldWillBlur
{
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[self reactTag]
type:RCTEventTextFieldWillBlur
nativeEventObj:@{@"target":self.reactTag}]];
}
@end

View File

@@ -8,7 +8,7 @@
@implementation RCTTextFieldManager
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
return [[RCTTextField alloc] initWithFrame:CGRectZero eventDispatcher:eventDispatcher];
}

View File

@@ -13,7 +13,7 @@
@implementation RCTTextManager
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
UILabel *label = [[UILabel alloc] init];
label.numberOfLines = 0;

View File

@@ -6,7 +6,7 @@
@implementation RCTUIActivityIndicatorViewManager
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
return [[UIActivityIndicatorView alloc] initWithFrame:CGRectZero];
}

View File

@@ -9,7 +9,7 @@
@implementation RCTUIViewManager
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
return [[UIView alloc] init];
}

View File

@@ -6,7 +6,7 @@
@implementation RCTViewManager
- (UIView *)viewWithEventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
return [[RCTView alloc] init];
}

View File

@@ -2,7 +2,7 @@
#import <UIKit/UIKit.h>
@class RCTJavaScriptEventDispatcher;
@class RCTEventDispatcher;
@class RCTNavItem;
@class RCTWrapperViewController;
@@ -15,8 +15,8 @@ didMoveToNavigationController:(UINavigationController *)navigationController;
@interface RCTWrapperViewController : UIViewController
- (instancetype)initWithContentView:(UIView *)contentView eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher;
- (instancetype)initWithNavItem:(RCTNavItem *)navItem eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher;
- (instancetype)initWithContentView:(UIView *)contentView eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
- (instancetype)initWithNavItem:(RCTNavItem *)navItem eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
@property (nonatomic, readwrite, weak) id<RCTWrapperViewControllerNavigationListener> navigationListener;
@property (nonatomic, strong, readwrite) RCTNavItem *navItem;

View File

@@ -2,8 +2,7 @@
#import "RCTWrapperViewController.h"
#import "RCTEventExtractor.h"
#import "RCTJavaScriptEventDispatcher.h"
#import "RCTEventDispatcher.h"
#import "RCTNavItem.h"
#import "RCTUtils.h"
#import "UIView+ReactKit.h"
@@ -11,7 +10,7 @@
@implementation RCTWrapperViewController
{
UIView *_contentView;
RCTJavaScriptEventDispatcher *_eventDispatcher;
RCTEventDispatcher *_eventDispatcher;
CGFloat _previousTopLayout;
CGFloat _previousBottomLayout;
}
@@ -21,9 +20,9 @@
RCT_NOT_DESIGNATED_INITIALIZER();
}
- (instancetype)initWithContentView:(UIView *)contentView eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (instancetype)initWithContentView:(UIView *)contentView eventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
if (self = [super initWithNibName:nil bundle:nil]) {
if ((self = [super initWithNibName:nil bundle:nil])) {
_contentView = contentView;
_eventDispatcher = eventDispatcher;
self.automaticallyAdjustsScrollViewInsets = NO;
@@ -31,9 +30,9 @@
return self;
}
- (instancetype)initWithNavItem:(RCTNavItem *)navItem eventDispatcher:(RCTJavaScriptEventDispatcher *)eventDispatcher
- (instancetype)initWithNavItem:(RCTNavItem *)navItem eventDispatcher:(RCTEventDispatcher *)eventDispatcher
{
if (self = [self initWithContentView:navItem eventDispatcher:eventDispatcher]) {
if ((self = [self initWithContentView:navItem eventDispatcher:eventDispatcher])) {
_navItem = navItem;
}
return self;
@@ -57,7 +56,7 @@
[[UIBarButtonItem alloc] initWithTitle:_navItem.rightButtonTitle
style:UIBarButtonItemStyleDone
target:self
action:@selector(_onRightButtonTapped:)];
action:@selector(rightButtonTapped)];
}
if (_navItem.backButtonTitle.length > 0) {
@@ -95,20 +94,9 @@
[self.view addSubview:_contentView];
}
- (void)_onRightButtonTapped:(id)sender
- (void)rightButtonTapped
{
RCTAssert(_navItem != nil, @"");
[self handleNavRightButtonTapped];
}
- (void)handleNavRightButtonTapped
{
NSDictionary *nativeEvent = @{
@"target":_navItem.reactTag
};
[_eventDispatcher sendEventWithArgs:[RCTEventExtractor eventArgs:[_navItem reactTag]
type:RCTEventNavRightButtonTap
nativeEventObj:nativeEvent]];
[_eventDispatcher sendRawEventWithType:@"topNavRightButtonTap" body:@{@"target":_navItem.reactTag}];
}
- (void)didMoveToParentViewController:(UIViewController *)parent