From 9f995a34686f86119f0b548e337a7eaf0e6d0a88 Mon Sep 17 00:00:00 2001 From: yogevbd Date: Tue, 26 Nov 2019 17:00:00 +0200 Subject: [PATCH 1/8] Prevent creation of button react view with the same componentId --- lib/ios/RNNNavigationButtons.m | 2 +- lib/ios/RNNReactComponentRegistry.h | 2 -- lib/ios/RNNReactComponentRegistry.m | 21 +++++---------------- lib/ios/RNNUIBarButtonItem.h | 2 +- lib/ios/RNNUIBarButtonItem.m | 20 +++++--------------- 5 files changed, 12 insertions(+), 35 deletions(-) diff --git a/lib/ios/RNNNavigationButtons.m b/lib/ios/RNNNavigationButtons.m index de9084e9b0c..2e224c1e9ca 100644 --- a/lib/ios/RNNNavigationButtons.m +++ b/lib/ios/RNNNavigationButtons.m @@ -104,7 +104,7 @@ -(RNNUIBarButtonItem*)buildButton: (NSDictionary*)dictionary defaultStyle:(RNNBu componentOptions.name = [[Text alloc] initWithValue:component[@"name"]]; RNNReactView *view = [_componentRegistry createComponentIfNotExists:componentOptions parentComponentId:self.viewController.layoutInfo.componentId reactViewReadyBlock:nil]; - barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withCustomView:view componentRegistry:_componentRegistry]; + barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withCustomView:view]; } else if (iconImage) { barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withIcon:iconImage]; } else if (title) { diff --git a/lib/ios/RNNReactComponentRegistry.h b/lib/ios/RNNReactComponentRegistry.h index 1c9fe513db1..ec3ff89fdbb 100644 --- a/lib/ios/RNNReactComponentRegistry.h +++ b/lib/ios/RNNReactComponentRegistry.h @@ -11,8 +11,6 @@ - (void)removeComponent:(NSString *)componentId; -- (void)removeChildComponent:(NSString *)childId; - - (void)clearComponentsForParentId:(NSString *)parentComponentId; - (void)clear; diff --git a/lib/ios/RNNReactComponentRegistry.m b/lib/ios/RNNReactComponentRegistry.m index bdaa582ad2b..9b8be13dee5 100644 --- a/lib/ios/RNNReactComponentRegistry.m +++ b/lib/ios/RNNReactComponentRegistry.m @@ -17,12 +17,12 @@ - (instancetype)initWithCreator:(id)creator { } - (RNNReactView *)createComponentIfNotExists:(RNNComponentOptions *)component parentComponentId:(NSString *)parentComponentId reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock { - NSMutableDictionary* parentComponentDict = [self componentsForParentId:parentComponentId]; + NSMapTable* parentComponentDict = [self componentsForParentId:parentComponentId]; - RNNReactView* reactView = parentComponentDict[component.componentId.get]; + RNNReactView* reactView = [parentComponentDict objectForKey:component.componentId.get]; if (!reactView) { reactView = (RNNReactView *)[_creator createRootViewFromComponentOptions:component reactViewReadyBlock:reactViewReadyBlock]; - parentComponentDict[component.componentId.get] = reactView; + [parentComponentDict setObject:reactView forKey:component.componentId.get]; } else if (reactViewReadyBlock) { reactViewReadyBlock(); } @@ -30,9 +30,9 @@ - (RNNReactView *)createComponentIfNotExists:(RNNComponentOptions *)component pa return reactView; } -- (NSMutableDictionary *)componentsForParentId:(NSString *)parentComponentId { +- (NSMapTable *)componentsForParentId:(NSString *)parentComponentId { if (![_componentStore objectForKey:parentComponentId]) { - [_componentStore setObject:[NSMutableDictionary new] forKey:parentComponentId];; + [_componentStore setObject:[NSMapTable weakToStrongObjectsMapTable] forKey:parentComponentId];; } return [_componentStore objectForKey:parentComponentId];; @@ -48,17 +48,6 @@ - (void)removeComponent:(NSString *)componentId { } } -- (void)removeChildComponent:(NSString *)childId { - NSMutableDictionary* parent; - NSEnumerator *enumerator = _componentStore.objectEnumerator; - while ((parent = enumerator.nextObject)) { - if (parent[childId]) { - [parent removeObjectForKey:childId]; - return; - } - } -} - - (void)clear { [_componentStore removeAllObjects]; } diff --git a/lib/ios/RNNUIBarButtonItem.h b/lib/ios/RNNUIBarButtonItem.h index 9a4db8d7adf..29c074cd8ee 100644 --- a/lib/ios/RNNUIBarButtonItem.h +++ b/lib/ios/RNNUIBarButtonItem.h @@ -9,7 +9,7 @@ -(instancetype)init:(NSString*)buttonId withIcon:(UIImage*)iconImage; -(instancetype)init:(NSString*)buttonId withTitle:(NSString*)title; --(instancetype)init:(NSString*)buttonId withCustomView:(RCTRootView *)reactView componentRegistry:(RNNReactComponentRegistry *)componentRegistry; +-(instancetype)init:(NSString*)buttonId withCustomView:(RCTRootView *)reactView; -(instancetype)init:(NSString*)buttonId withSystemItem:(NSString*)systemItemName; @end diff --git a/lib/ios/RNNUIBarButtonItem.m b/lib/ios/RNNUIBarButtonItem.m index 32b78108923..a3adf33e5a6 100644 --- a/lib/ios/RNNUIBarButtonItem.m +++ b/lib/ios/RNNUIBarButtonItem.m @@ -7,7 +7,6 @@ @interface RNNUIBarButtonItem () @property (nonatomic, strong) NSLayoutConstraint *widthConstraint; @property (nonatomic, strong) NSLayoutConstraint *heightConstraint; -@property (nonatomic, weak) RNNReactComponentRegistry *componentRegistry; @end @@ -29,29 +28,28 @@ -(instancetype)init:(NSString*)buttonId withTitle:(NSString*)title { return self; } --(instancetype)init:(NSString*)buttonId withCustomView:(RCTRootView *)reactView componentRegistry:(RNNReactComponentRegistry *)componentRegistry { +-(instancetype)init:(NSString*)buttonId withCustomView:(RCTRootView *)reactView { self = [super initWithCustomView:reactView]; - self.componentRegistry = componentRegistry; reactView.sizeFlexibility = RCTRootViewSizeFlexibilityWidthAndHeight; reactView.delegate = self; reactView.backgroundColor = [UIColor clearColor]; - reactView.hidden = YES; - + + [NSLayoutConstraint deactivateConstraints:reactView.constraints]; self.widthConstraint = [NSLayoutConstraint constraintWithItem:reactView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 - constant:1.0]; + constant:reactView.intrinsicContentSize.width]; self.heightConstraint = [NSLayoutConstraint constraintWithItem:reactView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 - constant:1.0]; + constant:reactView.intrinsicContentSize.height]; [NSLayoutConstraint activateConstraints:@[self.widthConstraint, self.heightConstraint]]; self.buttonId = buttonId; return self; @@ -65,7 +63,6 @@ - (instancetype)init:(NSString*)buttonId withSystemItem:(NSString *)systemItemNa } - (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView { - rootView.hidden = NO; self.widthConstraint.constant = rootView.intrinsicContentSize.width; self.heightConstraint.constant = rootView.intrinsicContentSize.height; [rootView setNeedsUpdateConstraints]; @@ -78,11 +75,4 @@ - (void)onButtonPressed { afterDelay:0]; } -- (void)dealloc { - if ([self.customView isKindOfClass:[RNNReactView class]]) { - RNNReactView* customView = self.customView; - [self.componentRegistry removeChildComponent:customView.componentId]; - } -} - @end From 096dc9327e5cbcfae5dcb729fe0ff422d5940ae1 Mon Sep 17 00:00:00 2001 From: yogevbd Date: Wed, 27 Nov 2019 11:28:42 +0200 Subject: [PATCH 2/8] Detach removed buttons --- lib/ios/RNNNavigationButtons.m | 16 +++++++++++++++- lib/ios/RNNReactComponentRegistry.h | 2 ++ lib/ios/RNNReactComponentRegistry.m | 11 +++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/ios/RNNNavigationButtons.m b/lib/ios/RNNNavigationButtons.m index 2e224c1e9ca..0b6ac5dcd0d 100644 --- a/lib/ios/RNNNavigationButtons.m +++ b/lib/ios/RNNNavigationButtons.m @@ -52,16 +52,30 @@ -(void)setButtons:(NSArray*)buttons side:(NSString*)side animated:(BOOL)animated self.viewController.navigationController.navigationBar.tintColor = color; } } - + if ([side isEqualToString:@"left"]) { + [self detachReactViews:barButtonItems oldButtons:self.viewController.navigationItem.leftBarButtonItems]; [self.viewController.navigationItem setLeftBarButtonItems:barButtonItems animated:animated]; } if ([side isEqualToString:@"right"]) { + [self detachReactViews:barButtonItems oldButtons:self.viewController.navigationItem.rightBarButtonItems]; [self.viewController.navigationItem setRightBarButtonItems:barButtonItems animated:animated]; } } +- (void)detachReactViews:(NSArray *)newButtons oldButtons:(NSArray *)oldButtons { + for (RNNUIBarButtonItem* barButtonItem in oldButtons) { + RNNReactView* reactView = barButtonItem.customView; + if ([reactView isKindOfClass:[RNNReactView class]]) { + NSArray* result = [newButtons filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"customView == %@", reactView]]; + if (!result.count) { + [_componentRegistry removeChildComponent:reactView.componentId]; + } + } + } +} + - (NSArray *)resolveButtons:(id)buttons { if ([buttons isKindOfClass:[NSArray class]]) { return buttons; diff --git a/lib/ios/RNNReactComponentRegistry.h b/lib/ios/RNNReactComponentRegistry.h index ec3ff89fdbb..1c9fe513db1 100644 --- a/lib/ios/RNNReactComponentRegistry.h +++ b/lib/ios/RNNReactComponentRegistry.h @@ -11,6 +11,8 @@ - (void)removeComponent:(NSString *)componentId; +- (void)removeChildComponent:(NSString *)childId; + - (void)clearComponentsForParentId:(NSString *)parentComponentId; - (void)clear; diff --git a/lib/ios/RNNReactComponentRegistry.m b/lib/ios/RNNReactComponentRegistry.m index 9b8be13dee5..1ad6f941d5e 100644 --- a/lib/ios/RNNReactComponentRegistry.m +++ b/lib/ios/RNNReactComponentRegistry.m @@ -48,6 +48,17 @@ - (void)removeComponent:(NSString *)componentId { } } +- (void)removeChildComponent:(NSString *)childId { + NSMapTable* parent; + NSEnumerator *enumerator = _componentStore.objectEnumerator; + while ((parent = enumerator.nextObject)) { + if ([parent objectForKey:childId]) { + [parent removeObjectForKey:childId]; + return; + } + } +} + - (void)clear { [_componentStore removeAllObjects]; } From 015d6f82156586b3a922ca78a09e6556ec6a8135 Mon Sep 17 00:00:00 2001 From: Yogev Ben David Date: Wed, 27 Nov 2019 12:16:26 +0200 Subject: [PATCH 3/8] Update RNNNavigationButtons.m --- lib/ios/RNNNavigationButtons.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ios/RNNNavigationButtons.m b/lib/ios/RNNNavigationButtons.m index 0b6ac5dcd0d..6ff10b3c0b0 100644 --- a/lib/ios/RNNNavigationButtons.m +++ b/lib/ios/RNNNavigationButtons.m @@ -54,17 +54,17 @@ -(void)setButtons:(NSArray*)buttons side:(NSString*)side animated:(BOOL)animated } if ([side isEqualToString:@"left"]) { - [self detachReactViews:barButtonItems oldButtons:self.viewController.navigationItem.leftBarButtonItems]; + [self clearPreviousButtonViews:barButtonItems oldButtons:self.viewController.navigationItem.leftBarButtonItems]; [self.viewController.navigationItem setLeftBarButtonItems:barButtonItems animated:animated]; } if ([side isEqualToString:@"right"]) { - [self detachReactViews:barButtonItems oldButtons:self.viewController.navigationItem.rightBarButtonItems]; + [self clearPreviousButtonViews:barButtonItems oldButtons:self.viewController.navigationItem.rightBarButtonItems]; [self.viewController.navigationItem setRightBarButtonItems:barButtonItems animated:animated]; } } -- (void)detachReactViews:(NSArray *)newButtons oldButtons:(NSArray *)oldButtons { +- (void)clearPreviousButtonViews:(NSArray *)newButtons oldButtons:(NSArray *)oldButtons { for (RNNUIBarButtonItem* barButtonItem in oldButtons) { RNNReactView* reactView = barButtonItem.customView; if ([reactView isKindOfClass:[RNNReactView class]]) { From fa5b19860e969b169edb2efa622c7ae07772d73c Mon Sep 17 00:00:00 2001 From: yogevbd Date: Wed, 27 Nov 2019 14:44:31 +0200 Subject: [PATCH 4/8] Refactor clearPreviousButtonViews --- lib/ios/NSArray+utils.h | 9 ++++++++ lib/ios/NSArray+utils.m | 23 +++++++++++++++++++ lib/ios/RNNNavigationButtons.m | 14 +++++------ .../project.pbxproj | 8 +++++++ 4 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 lib/ios/NSArray+utils.h create mode 100644 lib/ios/NSArray+utils.m diff --git a/lib/ios/NSArray+utils.h b/lib/ios/NSArray+utils.h new file mode 100644 index 00000000000..4d43b789676 --- /dev/null +++ b/lib/ios/NSArray+utils.h @@ -0,0 +1,9 @@ +#import + +@interface NSArray (utils) + +- (NSArray*)intersect:(NSArray *)array withPropertyName:(NSString *)propertyName; + +- (NSArray*)difference:(NSArray *)array withPropertyName:(NSString *)propertyName; + +@end diff --git a/lib/ios/NSArray+utils.m b/lib/ios/NSArray+utils.m new file mode 100644 index 00000000000..6f582142dc0 --- /dev/null +++ b/lib/ios/NSArray+utils.m @@ -0,0 +1,23 @@ +#import "NSArray+utils.h" + +@implementation NSArray (utils) + +- (NSArray*)intersect:(NSArray *)array withPropertyName:(NSString *)propertyName { + NSMutableArray* result = [NSMutableArray new]; + for (NSObject* object in array) { + NSArray* filteredArray = [self filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"%@ == %@", propertyName, object]]; + [result addObjectsFromArray:filteredArray]; + } + + return [NSArray arrayWithArray:result]; +} + +- (NSArray*)difference:(NSArray *)array withPropertyName:(NSString *)propertyName { + NSMutableArray* diff = [NSMutableArray arrayWithArray:self]; + NSArray* intersect = [self intersect:array withPropertyName:propertyName]; + [diff removeObjectsInArray:intersect]; + + return diff; +} + +@end diff --git a/lib/ios/RNNNavigationButtons.m b/lib/ios/RNNNavigationButtons.m index 6ff10b3c0b0..e366ae8847d 100644 --- a/lib/ios/RNNNavigationButtons.m +++ b/lib/ios/RNNNavigationButtons.m @@ -7,6 +7,7 @@ #import "UIImage+insets.h" #import "UIViewController+LayoutProtocol.h" #import "RNNFontAttributesCreator.h" +#import "NSArray+utils.h" @interface RNNNavigationButtons() @@ -65,14 +66,13 @@ -(void)setButtons:(NSArray*)buttons side:(NSString*)side animated:(BOOL)animated } - (void)clearPreviousButtonViews:(NSArray *)newButtons oldButtons:(NSArray *)oldButtons { - for (RNNUIBarButtonItem* barButtonItem in oldButtons) { + NSArray* removedButtons = [oldButtons difference:newButtons withPropertyName:@"customView"]; + + for (UIBarButtonItem* barButtonItem in removedButtons) { RNNReactView* reactView = barButtonItem.customView; - if ([reactView isKindOfClass:[RNNReactView class]]) { - NSArray* result = [newButtons filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"customView == %@", reactView]]; - if (!result.count) { - [_componentRegistry removeChildComponent:reactView.componentId]; - } - } + if ([reactView isKindOfClass:[RNNReactView class]]) { + [_componentRegistry removeChildComponent:reactView.componentId]; + } } } diff --git a/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj b/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj index e2426b886ca..e996dcaac36 100644 --- a/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj +++ b/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj @@ -224,6 +224,8 @@ 50CE8503217C6C9B00084EBF /* RNNSideMenuPresenterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 50CE8502217C6C9B00084EBF /* RNNSideMenuPresenterTest.m */; }; 50D031342005149000386B3D /* RNNOverlayManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 50D031322005149000386B3D /* RNNOverlayManager.h */; }; 50D031352005149000386B3D /* RNNOverlayManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 50D031332005149000386B3D /* RNNOverlayManager.m */; }; + 50DE2E45238EA14E005CD5F4 /* NSArray+utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 50DE2E43238EA14E005CD5F4 /* NSArray+utils.h */; }; + 50DE2E46238EA14E005CD5F4 /* NSArray+utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 50DE2E44238EA14E005CD5F4 /* NSArray+utils.m */; }; 50E02BD821A6EE0F00A43942 /* SideMenuOpenMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 50E02BD621A6EE0F00A43942 /* SideMenuOpenMode.h */; }; 50E02BD921A6EE0F00A43942 /* SideMenuOpenMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 50E02BD721A6EE0F00A43942 /* SideMenuOpenMode.m */; }; 50E02BDC21A6EE7900A43942 /* SideMenuOpenGestureModeParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 50E02BDA21A6EE7900A43942 /* SideMenuOpenGestureModeParser.m */; }; @@ -575,6 +577,8 @@ 50D031322005149000386B3D /* RNNOverlayManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNOverlayManager.h; sourceTree = ""; }; 50D031332005149000386B3D /* RNNOverlayManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNOverlayManager.m; sourceTree = ""; }; 50DA74CF232F80FE004A00C1 /* RCTConvert+UIFontWeight.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+UIFontWeight.h"; sourceTree = ""; }; + 50DE2E43238EA14E005CD5F4 /* NSArray+utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSArray+utils.h"; sourceTree = ""; }; + 50DE2E44238EA14E005CD5F4 /* NSArray+utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSArray+utils.m"; sourceTree = ""; }; 50E02BD521A6E54B00A43942 /* RCTConvert+SideMenuOpenGestureMode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+SideMenuOpenGestureMode.h"; sourceTree = ""; }; 50E02BD621A6EE0F00A43942 /* SideMenuOpenMode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SideMenuOpenMode.h; sourceTree = ""; }; 50E02BD721A6EE0F00A43942 /* SideMenuOpenMode.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SideMenuOpenMode.m; sourceTree = ""; }; @@ -1179,6 +1183,8 @@ E5F6C39E22DB4D0E0093C2CE /* UIViewController+Utils.m */, 50A409C8238D444900D5FF7D /* UINavigationBar+utils.h */, 50A409C9238D444900D5FF7D /* UINavigationBar+utils.m */, + 50DE2E43238EA14E005CD5F4 /* NSArray+utils.h */, + 50DE2E44238EA14E005CD5F4 /* NSArray+utils.m */, ); name = Utils; sourceTree = ""; @@ -1307,6 +1313,7 @@ 50644A2020E11A720026709C /* Constants.h in Headers */, E5F6C3AF22DB4D0F0093C2CE /* UIView+Utils.h in Headers */, 5012241E217366D4000F5F98 /* ColorParser.h in Headers */, + 50DE2E45238EA14E005CD5F4 /* NSArray+utils.h in Headers */, E8367B801F7A8A4700675C05 /* VICMAImageView.h in Headers */, 263905E61E4CAC950023D7D3 /* RNNSideMenuChildVC.h in Headers */, 50F5DFC51F407AA0001A00BC /* RNNStackController.h in Headers */, @@ -1527,6 +1534,7 @@ 50E5F78E223F9FAF002AFEAD /* RNNElementTransitionOptions.m in Sources */, 7365071221E4B16F004E020F /* RCTConvert+UIBarButtonSystemItem.m in Sources */, 5012241B21736678000F5F98 /* Image.m in Sources */, + 50DE2E46238EA14E005CD5F4 /* NSArray+utils.m in Sources */, 50495943216F5E5D006D2B81 /* NullBool.m in Sources */, 5038A3C7216E2D93009280BC /* Number.m in Sources */, E5F6C3A622DB4D0F0093C2CE /* UIViewController+Utils.m in Sources */, From 8d5793b78ace682473a39d9cd6e7ac75c4206442 Mon Sep 17 00:00:00 2001 From: yogevbd Date: Wed, 27 Nov 2019 14:47:45 +0200 Subject: [PATCH 5/8] Namings --- lib/ios/NSArray+utils.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/ios/NSArray+utils.m b/lib/ios/NSArray+utils.m index 6f582142dc0..a33cb74cd47 100644 --- a/lib/ios/NSArray+utils.m +++ b/lib/ios/NSArray+utils.m @@ -3,21 +3,21 @@ @implementation NSArray (utils) - (NSArray*)intersect:(NSArray *)array withPropertyName:(NSString *)propertyName { - NSMutableArray* result = [NSMutableArray new]; + NSMutableArray* intersection = [NSMutableArray new]; for (NSObject* object in array) { NSArray* filteredArray = [self filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"%@ == %@", propertyName, object]]; - [result addObjectsFromArray:filteredArray]; + [intersection addObjectsFromArray:filteredArray]; } - return [NSArray arrayWithArray:result]; + return [NSArray arrayWithArray:intersection]; } - (NSArray*)difference:(NSArray *)array withPropertyName:(NSString *)propertyName { NSMutableArray* diff = [NSMutableArray arrayWithArray:self]; - NSArray* intersect = [self intersect:array withPropertyName:propertyName]; - [diff removeObjectsInArray:intersect]; + NSArray* intersection = [self intersect:array withPropertyName:propertyName]; + [diff removeObjectsInArray:intersection]; - return diff; + return [NSArray arrayWithArray:diff]; } @end From 503392b3a3dbce176404ad47479beb558532dc6f Mon Sep 17 00:00:00 2001 From: yogevbd Date: Wed, 27 Nov 2019 15:19:25 +0200 Subject: [PATCH 6/8] Refactor RNNNavigationButtons.m --- lib/ios/NSArray+utils.h | 6 ++++-- lib/ios/NSArray+utils.m | 12 ++++++++++-- lib/ios/RNNNavigationButtons.m | 13 +++++++------ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/lib/ios/NSArray+utils.h b/lib/ios/NSArray+utils.h index 4d43b789676..4cbb168065b 100644 --- a/lib/ios/NSArray+utils.h +++ b/lib/ios/NSArray+utils.h @@ -2,8 +2,10 @@ @interface NSArray (utils) -- (NSArray*)intersect:(NSArray *)array withPropertyName:(NSString *)propertyName; +- (NSArray *)intersect:(NSArray *)array withPropertyName:(NSString *)propertyName; -- (NSArray*)difference:(NSArray *)array withPropertyName:(NSString *)propertyName; +- (NSArray *)difference:(NSArray *)array withPropertyName:(NSString *)propertyName; + +- (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block; @end diff --git a/lib/ios/NSArray+utils.m b/lib/ios/NSArray+utils.m index a33cb74cd47..24131f25cdd 100644 --- a/lib/ios/NSArray+utils.m +++ b/lib/ios/NSArray+utils.m @@ -2,7 +2,7 @@ @implementation NSArray (utils) -- (NSArray*)intersect:(NSArray *)array withPropertyName:(NSString *)propertyName { +- (NSArray *)intersect:(NSArray *)array withPropertyName:(NSString *)propertyName { NSMutableArray* intersection = [NSMutableArray new]; for (NSObject* object in array) { NSArray* filteredArray = [self filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"%@ == %@", propertyName, object]]; @@ -12,7 +12,7 @@ - (NSArray*)intersect:(NSArray *)array withPropertyName:(NSString *)propertyName return [NSArray arrayWithArray:intersection]; } -- (NSArray*)difference:(NSArray *)array withPropertyName:(NSString *)propertyName { +- (NSArray *)difference:(NSArray *)array withPropertyName:(NSString *)propertyName { NSMutableArray* diff = [NSMutableArray arrayWithArray:self]; NSArray* intersection = [self intersect:array withPropertyName:propertyName]; [diff removeObjectsInArray:intersection]; @@ -20,4 +20,12 @@ - (NSArray*)difference:(NSArray *)array withPropertyName:(NSString *)propertyNam return [NSArray arrayWithArray:diff]; } +- (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block { + NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]]; + [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + [result addObject:block(obj, idx)]; + }]; + return result; +} + @end diff --git a/lib/ios/RNNNavigationButtons.m b/lib/ios/RNNNavigationButtons.m index e366ae8847d..6a84abe8dc4 100644 --- a/lib/ios/RNNNavigationButtons.m +++ b/lib/ios/RNNNavigationButtons.m @@ -66,13 +66,14 @@ -(void)setButtons:(NSArray*)buttons side:(NSString*)side animated:(BOOL)animated } - (void)clearPreviousButtonViews:(NSArray *)newButtons oldButtons:(NSArray *)oldButtons { - NSArray* removedButtons = [oldButtons difference:newButtons withPropertyName:@"customView"]; + NSArray* removedButtonViews = [[[oldButtons difference:newButtons withPropertyName:@"customView"] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UIBarButtonItem* _Nullable buttonItem, NSDictionary * _Nullable bindings) { + return [buttonItem.customView isKindOfClass:[RNNReactView class]]; + }]] mapObjectsUsingBlock:^id(UIBarButtonItem* buttonItem, NSUInteger idx) { + return buttonItem.customView; + }]; - for (UIBarButtonItem* barButtonItem in removedButtons) { - RNNReactView* reactView = barButtonItem.customView; - if ([reactView isKindOfClass:[RNNReactView class]]) { - [_componentRegistry removeChildComponent:reactView.componentId]; - } + for (RNNReactView* buttonView in removedButtonViews) { + [_componentRegistry removeChildComponent:buttonView.componentId]; } } From 40306e3c3644cce93e7112ce459f04149f251fe0 Mon Sep 17 00:00:00 2001 From: yogevbd Date: Wed, 27 Nov 2019 15:20:17 +0200 Subject: [PATCH 7/8] f --- lib/ios/RNNNavigationButtons.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ios/RNNNavigationButtons.m b/lib/ios/RNNNavigationButtons.m index 6a84abe8dc4..fccdd3e96cb 100644 --- a/lib/ios/RNNNavigationButtons.m +++ b/lib/ios/RNNNavigationButtons.m @@ -72,8 +72,8 @@ - (void)clearPreviousButtonViews:(NSArray *)newButtons oldBut return buttonItem.customView; }]; - for (RNNReactView* buttonView in removedButtonViews) { - [_componentRegistry removeChildComponent:buttonView.componentId]; + for (RNNReactView* reactView in removedButtonViews) { + [_componentRegistry removeChildComponent:reactView.componentId]; } } From b5b8b36e8785a46a6beb0495c9e9d2aa06ed8f9e Mon Sep 17 00:00:00 2001 From: yogevbd Date: Wed, 27 Nov 2019 15:37:20 +0200 Subject: [PATCH 8/8] f --- lib/ios/RNNNavigationButtons.m | 295 ++++++++++++++++----------------- 1 file changed, 147 insertions(+), 148 deletions(-) diff --git a/lib/ios/RNNNavigationButtons.m b/lib/ios/RNNNavigationButtons.m index fccdd3e96cb..0f0e3396fe5 100644 --- a/lib/ios/RNNNavigationButtons.m +++ b/lib/ios/RNNNavigationButtons.m @@ -20,181 +20,180 @@ @interface RNNNavigationButtons() @implementation RNNNavigationButtons -(instancetype)initWithViewController:(UIViewController*)viewController componentRegistry:(id)componentRegistry { - self = [super init]; - - self.viewController = viewController; - self.componentRegistry = componentRegistry; - - return self; + self = [super init]; + + self.viewController = viewController; + self.componentRegistry = componentRegistry; + + return self; } - (void)applyLeftButtons:(NSArray *)leftButtons rightButtons:(NSArray *)rightButtons defaultLeftButtonStyle:(RNNButtonOptions *)defaultLeftButtonStyle defaultRightButtonStyle:(RNNButtonOptions *)defaultRightButtonStyle { - _defaultLeftButtonStyle = defaultLeftButtonStyle; - _defaultRightButtonStyle = defaultRightButtonStyle; - if (leftButtons) { - [self setButtons:leftButtons side:@"left" animated:NO defaultStyle:_defaultLeftButtonStyle insets:[self leftButtonInsets:_defaultLeftButtonStyle.iconInsets]]; - } - - if (rightButtons) { - [self setButtons:rightButtons side:@"right" animated:NO defaultStyle:_defaultRightButtonStyle insets:[self rightButtonInsets:_defaultRightButtonStyle.iconInsets]]; - } + _defaultLeftButtonStyle = defaultLeftButtonStyle; + _defaultRightButtonStyle = defaultRightButtonStyle; + if (leftButtons) { + [self setButtons:leftButtons side:@"left" animated:NO defaultStyle:_defaultLeftButtonStyle insets:[self leftButtonInsets:_defaultLeftButtonStyle.iconInsets]]; + } + + if (rightButtons) { + [self setButtons:rightButtons side:@"right" animated:NO defaultStyle:_defaultRightButtonStyle insets:[self rightButtonInsets:_defaultRightButtonStyle.iconInsets]]; + } } -(void)setButtons:(NSArray*)buttons side:(NSString*)side animated:(BOOL)animated defaultStyle:(RNNButtonOptions *)defaultStyle insets:(UIEdgeInsets)insets { - NSMutableArray *barButtonItems = [NSMutableArray new]; - NSArray* resolvedButtons = [self resolveButtons:buttons]; - for (NSDictionary *button in resolvedButtons) { - RNNUIBarButtonItem* barButtonItem = [self buildButton:button defaultStyle:defaultStyle insets:insets]; - if(barButtonItem) { - [barButtonItems addObject:barButtonItem]; - } - UIColor* color = [self color:[RCTConvert UIColor:button[@"color"]] defaultColor:[defaultStyle.color getWithDefaultValue:nil]]; - if (color) { - self.viewController.navigationController.navigationBar.tintColor = color; - } - } - - if ([side isEqualToString:@"left"]) { - [self clearPreviousButtonViews:barButtonItems oldButtons:self.viewController.navigationItem.leftBarButtonItems]; - [self.viewController.navigationItem setLeftBarButtonItems:barButtonItems animated:animated]; - } - - if ([side isEqualToString:@"right"]) { - [self clearPreviousButtonViews:barButtonItems oldButtons:self.viewController.navigationItem.rightBarButtonItems]; - [self.viewController.navigationItem setRightBarButtonItems:barButtonItems animated:animated]; - } + NSMutableArray *barButtonItems = [NSMutableArray new]; + NSArray* resolvedButtons = [self resolveButtons:buttons]; + for (NSDictionary *button in resolvedButtons) { + RNNUIBarButtonItem* barButtonItem = [self buildButton:button defaultStyle:defaultStyle insets:insets]; + if(barButtonItem) { + [barButtonItems addObject:barButtonItem]; + } + UIColor* color = [self color:[RCTConvert UIColor:button[@"color"]] defaultColor:[defaultStyle.color getWithDefaultValue:nil]]; + if (color) { + self.viewController.navigationController.navigationBar.tintColor = color; + } + } + + if ([side isEqualToString:@"left"]) { + [self clearPreviousButtonViews:barButtonItems oldButtons:self.viewController.navigationItem.leftBarButtonItems]; + [self.viewController.navigationItem setLeftBarButtonItems:barButtonItems animated:animated]; + } + + if ([side isEqualToString:@"right"]) { + [self clearPreviousButtonViews:barButtonItems oldButtons:self.viewController.navigationItem.rightBarButtonItems]; + [self.viewController.navigationItem setRightBarButtonItems:barButtonItems animated:animated]; + } } - (void)clearPreviousButtonViews:(NSArray *)newButtons oldButtons:(NSArray *)oldButtons { - NSArray* removedButtonViews = [[[oldButtons difference:newButtons withPropertyName:@"customView"] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UIBarButtonItem* _Nullable buttonItem, NSDictionary * _Nullable bindings) { - return [buttonItem.customView isKindOfClass:[RNNReactView class]]; - }]] mapObjectsUsingBlock:^id(UIBarButtonItem* buttonItem, NSUInteger idx) { - return buttonItem.customView; - }]; - - for (RNNReactView* reactView in removedButtonViews) { - [_componentRegistry removeChildComponent:reactView.componentId]; - } + NSArray* removedButtons = [oldButtons difference:newButtons withPropertyName:@"customView"]; + + for (UIBarButtonItem* buttonItem in removedButtons) { + RNNReactView* reactView = buttonItem.customView; + if ([reactView isKindOfClass:[RNNReactView class]]) { + [_componentRegistry removeChildComponent:reactView.componentId]; + } + } } - (NSArray *)resolveButtons:(id)buttons { - if ([buttons isKindOfClass:[NSArray class]]) { - return buttons; - } else { - return @[buttons]; - } + if ([buttons isKindOfClass:[NSArray class]]) { + return buttons; + } else { + return @[buttons]; + } } -(RNNUIBarButtonItem*)buildButton: (NSDictionary*)dictionary defaultStyle:(RNNButtonOptions *)defaultStyle insets:(UIEdgeInsets)insets { - NSString* buttonId = dictionary[@"id"]; - NSString* title = [self getValue:dictionary[@"text"] withDefault:[defaultStyle.text getWithDefaultValue:nil]]; - NSDictionary* component = dictionary[@"component"]; - NSString* systemItemName = dictionary[@"systemItem"]; - - UIColor* color = [self color:[RCTConvert UIColor:dictionary[@"color"]] defaultColor:[defaultStyle.color getWithDefaultValue:nil]]; - UIColor* disabledColor = [self color:[RCTConvert UIColor:dictionary[@"disabledColor"]] defaultColor:[defaultStyle.disabledColor getWithDefaultValue:nil]]; - - if (!buttonId) { - @throw [NSException exceptionWithName:@"NSInvalidArgumentException" reason:[@"button id is not specified " stringByAppendingString:title] userInfo:nil]; - } - - UIImage* defaultIcon = [defaultStyle.icon getWithDefaultValue:nil]; - UIImage* iconImage = [self getValue:dictionary[@"icon"] withDefault:defaultIcon]; - if (![iconImage isKindOfClass:[UIImage class]]) { - iconImage = [RCTConvert UIImage:iconImage]; - } - - if (iconImage) { - iconImage = [iconImage imageWithInsets:insets]; - if (color) { - iconImage = [iconImage withTintColor:color]; - } - } - - - RNNUIBarButtonItem *barButtonItem; - if (component) { - RNNComponentOptions* componentOptions = [RNNComponentOptions new]; - componentOptions.componentId = [[Text alloc] initWithValue:component[@"componentId"]]; - componentOptions.name = [[Text alloc] initWithValue:component[@"name"]]; - - RNNReactView *view = [_componentRegistry createComponentIfNotExists:componentOptions parentComponentId:self.viewController.layoutInfo.componentId reactViewReadyBlock:nil]; - barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withCustomView:view]; - } else if (iconImage) { - barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withIcon:iconImage]; - } else if (title) { - barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withTitle:title]; - - NSMutableDictionary *buttonTextAttributes = [RCTHelpers textAttributesFromDictionary:dictionary withPrefix:@"button"]; - if (buttonTextAttributes.allKeys.count > 0) { - [barButtonItem setTitleTextAttributes:buttonTextAttributes forState:UIControlStateNormal]; - } - } else if (systemItemName) { - barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withSystemItem:systemItemName]; - } else { - return nil; - } - - barButtonItem.target = self.viewController; - barButtonItem.action = @selector(onButtonPress:); - - NSNumber *enabled = [self getValue:dictionary[@"enabled"] withDefault:defaultStyle.enabled.getValue]; - BOOL enabledBool = enabled ? [enabled boolValue] : YES; - [barButtonItem setEnabled:enabledBool]; - - NSMutableDictionary* textAttributes = [NSMutableDictionary dictionaryWithDictionary:[RNNFontAttributesCreator createWithFontFamily:dictionary[@"fontFamily"] ?: [defaultStyle.fontFamily getWithDefaultValue:nil] fontSize:dictionary[@"fontSize"] defaultFontSize:[defaultStyle.fontSize getWithDefaultValue:@(17)] fontWeight:dictionary[@"fontWeight"] color:nil defaultColor:nil]]; - NSMutableDictionary* disabledTextAttributes = [NSMutableDictionary dictionaryWithDictionary:[RNNFontAttributesCreator createWithFontFamily:dictionary[@"fontFamily"] ?: [defaultStyle.fontFamily getWithDefaultValue:nil] fontSize:dictionary[@"fontSize"] defaultFontSize:[defaultStyle.fontSize getWithDefaultValue:@(17)] fontWeight:dictionary[@"fontWeight"] color:nil defaultColor:nil]]; - - if (!enabledBool && disabledColor) { - color = disabledColor; - [disabledTextAttributes setObject:disabledColor forKey:NSForegroundColorAttributeName]; - } - - if (color) { - [textAttributes setObject:color forKey:NSForegroundColorAttributeName]; - [barButtonItem setImage:[[iconImage withTintColor:color] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]]; - barButtonItem.tintColor = color; - } - - [barButtonItem setTitleTextAttributes:textAttributes forState:UIControlStateNormal]; - [barButtonItem setTitleTextAttributes:textAttributes forState:UIControlStateHighlighted]; - [barButtonItem setTitleTextAttributes:disabledTextAttributes forState:UIControlStateDisabled]; - - NSString *testID = dictionary[@"testID"]; - if (testID) - { - barButtonItem.accessibilityIdentifier = testID; - } - - return barButtonItem; + NSString* buttonId = dictionary[@"id"]; + NSString* title = [self getValue:dictionary[@"text"] withDefault:[defaultStyle.text getWithDefaultValue:nil]]; + NSDictionary* component = dictionary[@"component"]; + NSString* systemItemName = dictionary[@"systemItem"]; + + UIColor* color = [self color:[RCTConvert UIColor:dictionary[@"color"]] defaultColor:[defaultStyle.color getWithDefaultValue:nil]]; + UIColor* disabledColor = [self color:[RCTConvert UIColor:dictionary[@"disabledColor"]] defaultColor:[defaultStyle.disabledColor getWithDefaultValue:nil]]; + + if (!buttonId) { + @throw [NSException exceptionWithName:@"NSInvalidArgumentException" reason:[@"button id is not specified " stringByAppendingString:title] userInfo:nil]; + } + + UIImage* defaultIcon = [defaultStyle.icon getWithDefaultValue:nil]; + UIImage* iconImage = [self getValue:dictionary[@"icon"] withDefault:defaultIcon]; + if (![iconImage isKindOfClass:[UIImage class]]) { + iconImage = [RCTConvert UIImage:iconImage]; + } + + if (iconImage) { + iconImage = [iconImage imageWithInsets:insets]; + if (color) { + iconImage = [iconImage withTintColor:color]; + } + } + + + RNNUIBarButtonItem *barButtonItem; + if (component) { + RNNComponentOptions* componentOptions = [RNNComponentOptions new]; + componentOptions.componentId = [[Text alloc] initWithValue:component[@"componentId"]]; + componentOptions.name = [[Text alloc] initWithValue:component[@"name"]]; + + RNNReactView *view = [_componentRegistry createComponentIfNotExists:componentOptions parentComponentId:self.viewController.layoutInfo.componentId reactViewReadyBlock:nil]; + barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withCustomView:view]; + } else if (iconImage) { + barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withIcon:iconImage]; + } else if (title) { + barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withTitle:title]; + + NSMutableDictionary *buttonTextAttributes = [RCTHelpers textAttributesFromDictionary:dictionary withPrefix:@"button"]; + if (buttonTextAttributes.allKeys.count > 0) { + [barButtonItem setTitleTextAttributes:buttonTextAttributes forState:UIControlStateNormal]; + } + } else if (systemItemName) { + barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withSystemItem:systemItemName]; + } else { + return nil; + } + + barButtonItem.target = self.viewController; + barButtonItem.action = @selector(onButtonPress:); + + NSNumber *enabled = [self getValue:dictionary[@"enabled"] withDefault:defaultStyle.enabled.getValue]; + BOOL enabledBool = enabled ? [enabled boolValue] : YES; + [barButtonItem setEnabled:enabledBool]; + + NSMutableDictionary* textAttributes = [NSMutableDictionary dictionaryWithDictionary:[RNNFontAttributesCreator createWithFontFamily:dictionary[@"fontFamily"] ?: [defaultStyle.fontFamily getWithDefaultValue:nil] fontSize:dictionary[@"fontSize"] defaultFontSize:[defaultStyle.fontSize getWithDefaultValue:@(17)] fontWeight:dictionary[@"fontWeight"] color:nil defaultColor:nil]]; + NSMutableDictionary* disabledTextAttributes = [NSMutableDictionary dictionaryWithDictionary:[RNNFontAttributesCreator createWithFontFamily:dictionary[@"fontFamily"] ?: [defaultStyle.fontFamily getWithDefaultValue:nil] fontSize:dictionary[@"fontSize"] defaultFontSize:[defaultStyle.fontSize getWithDefaultValue:@(17)] fontWeight:dictionary[@"fontWeight"] color:nil defaultColor:nil]]; + + if (!enabledBool && disabledColor) { + color = disabledColor; + [disabledTextAttributes setObject:disabledColor forKey:NSForegroundColorAttributeName]; + } + + if (color) { + [textAttributes setObject:color forKey:NSForegroundColorAttributeName]; + [barButtonItem setImage:[[iconImage withTintColor:color] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]]; + barButtonItem.tintColor = color; + } + + [barButtonItem setTitleTextAttributes:textAttributes forState:UIControlStateNormal]; + [barButtonItem setTitleTextAttributes:textAttributes forState:UIControlStateHighlighted]; + [barButtonItem setTitleTextAttributes:disabledTextAttributes forState:UIControlStateDisabled]; + + NSString *testID = dictionary[@"testID"]; + if (testID) + { + barButtonItem.accessibilityIdentifier = testID; + } + + return barButtonItem; } - (UIColor *)color:(UIColor *)color defaultColor:(UIColor *)defaultColor { - if (color) { - return color; - } else if (defaultColor) { - return defaultColor; - } - - return nil; + if (color) { + return color; + } else if (defaultColor) { + return defaultColor; + } + + return nil; } - (id)getValue:(id)value withDefault:(id)defaultValue { - return value ? value : defaultValue; + return value ? value : defaultValue; } - (UIEdgeInsets)leftButtonInsets:(RNNInsetsOptions *)defaultInsets { - return UIEdgeInsetsMake([defaultInsets.top getWithDefaultValue:0], - [defaultInsets.left getWithDefaultValue:0], - [defaultInsets.bottom getWithDefaultValue:0], - [defaultInsets.right getWithDefaultValue:15]); + return UIEdgeInsetsMake([defaultInsets.top getWithDefaultValue:0], + [defaultInsets.left getWithDefaultValue:0], + [defaultInsets.bottom getWithDefaultValue:0], + [defaultInsets.right getWithDefaultValue:15]); } - (UIEdgeInsets)rightButtonInsets:(RNNInsetsOptions *)defaultInsets { - return UIEdgeInsetsMake([defaultInsets.top getWithDefaultValue:0], - [defaultInsets.left getWithDefaultValue:15], - [defaultInsets.bottom getWithDefaultValue:0], - [defaultInsets.right getWithDefaultValue:0]); + return UIEdgeInsetsMake([defaultInsets.top getWithDefaultValue:0], + [defaultInsets.left getWithDefaultValue:15], + [defaultInsets.bottom getWithDefaultValue:0], + [defaultInsets.right getWithDefaultValue:0]); } @end