Skip to content

Commit cc659b4

Browse files
krystiansliwaKrystian ŚliwaPiotr Trocki
authored
fix(ios): refactor iOS code (#189)
* Change code to more modern objc * Use NSInteger for goTo argument * Wrap constraints code into @available * Save scrollview reference for later use * Refactor to not use ivars, extract some methods, remove childrenViewControllers * Cache controllers to reuse the both when using gestures and goTo * WIP change way of caching controllers * Remove unneeded code + use new mechanism for caching controllers both from gesture based callbacks and goTo * Extract classes with events from ReactNativePageView class * Fix react native viewpager iOS main project * Reorganize some code * Use sender instead of direct call to object * Support removing pages * Remove isMoving flag + reuse controller in nextController method * Add findAndCacheController * fix example Co-authored-by: Krystian Śliwa <[email protected]> Co-authored-by: Piotr Trocki <[email protected]>
1 parent 54346b2 commit cc659b4

13 files changed

+477
-390
lines changed

example/src/component/ProgressBar.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export class ProgressBar extends React.Component<Props> {
3030
(fractionalPosition / (this.props.numberOfPages - 1)) * this.props.size;
3131
}
3232

33+
progressBarSize = isNaN(progressBarSize) ? 0 : progressBarSize;
34+
3335
return (
3436
<View style={[styles.progressBarContainer, {width: this.props.size}]}>
3537
<View style={[styles.progressBar, {width: progressBarSize}]} />

ios/RCTOnPageScrollEvent.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#import <Foundation/Foundation.h>
2+
#import <React/RCTViewManager.h>
3+
4+
NS_ASSUME_NONNULL_BEGIN
5+
6+
@interface RCTOnPageScrollEvent : NSObject <RCTEvent>
7+
8+
- (instancetype) initWithReactTag:(NSNumber *)reactTag
9+
position:(NSNumber *)position
10+
offset:(NSNumber *)offset;
11+
12+
@end
13+
14+
NS_ASSUME_NONNULL_END

ios/RCTOnPageScrollEvent.m

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#import <React/UIView+React.h>
2+
#import "RCTOnPageScrollEvent.h"
3+
4+
@implementation RCTOnPageScrollEvent
5+
{
6+
NSNumber* _position;
7+
NSNumber* _offset;
8+
}
9+
10+
@synthesize viewTag = _viewTag;
11+
12+
- (NSString *)eventName {
13+
return @"onPageScroll";
14+
}
15+
16+
- (instancetype) initWithReactTag:(NSNumber *)reactTag
17+
position:(NSNumber *)position
18+
offset:(NSNumber *)offset;
19+
{
20+
RCTAssertParam(reactTag);
21+
22+
if ((self = [super init])) {
23+
_viewTag = reactTag;
24+
_position = position;
25+
_offset = offset;
26+
}
27+
return self;
28+
}
29+
30+
RCT_NOT_IMPLEMENTED(- (instancetype)init)
31+
- (uint16_t)coalescingKey
32+
{
33+
return 0;
34+
}
35+
36+
37+
- (BOOL)canCoalesce
38+
{
39+
return YES;
40+
}
41+
42+
+ (NSString *)moduleDotMethod
43+
{
44+
return @"RCTEventEmitter.receiveEvent";
45+
}
46+
47+
- (NSArray *)arguments
48+
{
49+
return @[self.viewTag, RCTNormalizeInputEventName(self.eventName), @{
50+
@"position": _position,
51+
@"offset": _offset
52+
}];
53+
}
54+
55+
- (id<RCTEvent>)coalesceWithEvent:(id<RCTEvent>)newEvent;
56+
{
57+
return newEvent;
58+
}
59+
60+
@end

ios/RCTOnPageScrollStateChanged.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#import <Foundation/Foundation.h>
2+
#import <React/RCTViewManager.h>
3+
4+
NS_ASSUME_NONNULL_BEGIN
5+
6+
@interface RCTOnPageScrollStateChanged : NSObject <RCTEvent>
7+
8+
- (instancetype) initWithReactTag:(NSNumber *)reactTag
9+
state:(NSString *)state
10+
coalescingKey:(uint16_t)coalescingKey;
11+
12+
@end
13+
14+
NS_ASSUME_NONNULL_END

ios/RCTOnPageScrollStateChanged.m

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#import <React/UIView+React.h>
2+
#import "RCTOnPageScrollStateChanged.h"
3+
4+
@implementation RCTOnPageScrollStateChanged
5+
{
6+
NSString* _state;
7+
uint16_t _coalescingKey;
8+
}
9+
10+
@synthesize viewTag = _viewTag;
11+
12+
- (NSString *)eventName {
13+
return @"onPageScrollStateChanged";
14+
}
15+
16+
- (instancetype) initWithReactTag:(NSNumber *)reactTag
17+
state:(NSString *)state
18+
coalescingKey:(uint16_t)coalescingKey;
19+
{
20+
RCTAssertParam(reactTag);
21+
22+
if ((self = [super init])) {
23+
_viewTag = reactTag;
24+
_state = state;
25+
_coalescingKey = coalescingKey;
26+
}
27+
return self;
28+
}
29+
30+
RCT_NOT_IMPLEMENTED(- (instancetype)init)
31+
- (uint16_t)coalescingKey
32+
{
33+
return _coalescingKey;
34+
}
35+
36+
37+
- (BOOL)canCoalesce
38+
{
39+
return NO;
40+
}
41+
42+
+ (NSString *)moduleDotMethod
43+
{
44+
return @"RCTEventEmitter.receiveEvent";
45+
}
46+
47+
- (NSArray *)arguments
48+
{
49+
return @[self.viewTag, RCTNormalizeInputEventName(self.eventName), @{
50+
@"pageScrollState": _state,
51+
}];
52+
}
53+
54+
- (id<RCTEvent>)coalesceWithEvent:(id<RCTEvent>)newEvent;
55+
{
56+
return newEvent;
57+
}
58+
59+
@end

ios/RCTOnPageSelected.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#import <Foundation/Foundation.h>
2+
#import <React/RCTViewManager.h>
3+
4+
NS_ASSUME_NONNULL_BEGIN
5+
6+
@interface RCTOnPageSelected : NSObject <RCTEvent>
7+
8+
- (instancetype) initWithReactTag:(NSNumber *)reactTag
9+
position:(NSNumber *)position
10+
coalescingKey:(uint16_t)coalescingKey;
11+
12+
@end
13+
14+
NS_ASSUME_NONNULL_END

ios/RCTOnPageSelected.m

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#import <React/UIView+React.h>
2+
#import "RCTOnPageSelected.h"
3+
4+
@implementation RCTOnPageSelected
5+
{
6+
NSNumber* _position;
7+
uint16_t _coalescingKey;
8+
}
9+
10+
@synthesize viewTag = _viewTag;
11+
12+
- (NSString *)eventName {
13+
return @"onPageSelected";
14+
}
15+
16+
- (instancetype) initWithReactTag:(NSNumber *)reactTag
17+
position:(NSNumber *)position
18+
coalescingKey:(uint16_t)coalescingKey;
19+
{
20+
RCTAssertParam(reactTag);
21+
22+
if ((self = [super init])) {
23+
_viewTag = reactTag;
24+
_position = position;
25+
_coalescingKey = coalescingKey;
26+
}
27+
return self;
28+
}
29+
30+
RCT_NOT_IMPLEMENTED(- (instancetype)init)
31+
- (uint16_t)coalescingKey
32+
{
33+
return _coalescingKey;
34+
}
35+
36+
37+
- (BOOL)canCoalesce
38+
{
39+
return NO;
40+
}
41+
42+
+ (NSString *)moduleDotMethod
43+
{
44+
return @"RCTEventEmitter.receiveEvent";
45+
}
46+
47+
- (NSArray *)arguments
48+
{
49+
return @[self.viewTag, RCTNormalizeInputEventName(self.eventName), @{
50+
@"position": _position,
51+
}];
52+
}
53+
54+
- (id<RCTEvent>)coalesceWithEvent:(id<RCTEvent>)newEvent;
55+
{
56+
return newEvent;
57+
}
58+
59+
@end
60+

ios/RNCViewpager.xcodeproj/project.pbxproj

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
0813B11424A6277400B13827 /* UIViewController+CreateExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 0813B11324A6277400B13827 /* UIViewController+CreateExtension.m */; };
11+
0813B11C24A627BA00B13827 /* RCTOnPageSelected.m in Sources */ = {isa = PBXBuildFile; fileRef = 0813B11624A627BA00B13827 /* RCTOnPageSelected.m */; };
12+
0813B11D24A627BA00B13827 /* RCTOnPageScrollStateChanged.m in Sources */ = {isa = PBXBuildFile; fileRef = 0813B11724A627BA00B13827 /* RCTOnPageScrollStateChanged.m */; };
13+
0813B11E24A627BA00B13827 /* RCTOnPageScrollEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 0813B11924A627BA00B13827 /* RCTOnPageScrollEvent.m */; };
1014
183B5ECB228BEC260013B58C /* ReactNativePageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 183B5ECA228BEC260013B58C /* ReactNativePageView.m */; };
1115
183B5FB8228DA0750013B58C /* RCTConvert+UIPageViewControllerTransitionStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 183B5FB7228DA0750013B58C /* RCTConvert+UIPageViewControllerTransitionStyle.m */; };
1216
183B5FBB228DA1220013B58C /* RCTConvert+UIPageViewControllerNavigationOrientation.m in Sources */ = {isa = PBXBuildFile; fileRef = 183B5FBA228DA1220013B58C /* RCTConvert+UIPageViewControllerNavigationOrientation.m */; };
@@ -26,6 +30,14 @@
2630
/* End PBXCopyFilesBuildPhase section */
2731

2832
/* Begin PBXFileReference section */
33+
0813B11224A6277400B13827 /* UIViewController+CreateExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+CreateExtension.h"; sourceTree = "<group>"; };
34+
0813B11324A6277400B13827 /* UIViewController+CreateExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+CreateExtension.m"; sourceTree = "<group>"; };
35+
0813B11624A627BA00B13827 /* RCTOnPageSelected.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTOnPageSelected.m; sourceTree = "<group>"; };
36+
0813B11724A627BA00B13827 /* RCTOnPageScrollStateChanged.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTOnPageScrollStateChanged.m; sourceTree = "<group>"; };
37+
0813B11824A627BA00B13827 /* RCTOnPageScrollEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTOnPageScrollEvent.h; sourceTree = "<group>"; };
38+
0813B11924A627BA00B13827 /* RCTOnPageScrollEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTOnPageScrollEvent.m; sourceTree = "<group>"; };
39+
0813B11A24A627BA00B13827 /* RCTOnPageScrollStateChanged.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTOnPageScrollStateChanged.h; sourceTree = "<group>"; };
40+
0813B11B24A627BA00B13827 /* RCTOnPageSelected.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTOnPageSelected.h; sourceTree = "<group>"; };
2941
134814201AA4EA6300B7C361 /* libRNCViewpager.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNCViewpager.a; sourceTree = BUILT_PRODUCTS_DIR; };
3042
183B5EC9228BEC260013B58C /* ReactNativePageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactNativePageView.h; sourceTree = "<group>"; };
3143
183B5ECA228BEC260013B58C /* ReactNativePageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReactNativePageView.m; sourceTree = "<group>"; };
@@ -48,6 +60,19 @@
4860
/* End PBXFrameworksBuildPhase section */
4961

5062
/* Begin PBXGroup section */
63+
0813B11524A627AC00B13827 /* Events */ = {
64+
isa = PBXGroup;
65+
children = (
66+
0813B11824A627BA00B13827 /* RCTOnPageScrollEvent.h */,
67+
0813B11924A627BA00B13827 /* RCTOnPageScrollEvent.m */,
68+
0813B11A24A627BA00B13827 /* RCTOnPageScrollStateChanged.h */,
69+
0813B11724A627BA00B13827 /* RCTOnPageScrollStateChanged.m */,
70+
0813B11B24A627BA00B13827 /* RCTOnPageSelected.h */,
71+
0813B11624A627BA00B13827 /* RCTOnPageSelected.m */,
72+
);
73+
name = Events;
74+
sourceTree = "<group>";
75+
};
5176
134814211AA4EA7D00B7C361 /* Products */ = {
5277
isa = PBXGroup;
5378
children = (
@@ -59,6 +84,8 @@
5984
183B5FB5228DA03B0013B58C /* Extension */ = {
6085
isa = PBXGroup;
6186
children = (
87+
0813B11224A6277400B13827 /* UIViewController+CreateExtension.h */,
88+
0813B11324A6277400B13827 /* UIViewController+CreateExtension.m */,
6289
183B5FB6228DA0750013B58C /* RCTConvert+UIPageViewControllerTransitionStyle.h */,
6390
183B5FB7228DA0750013B58C /* RCTConvert+UIPageViewControllerTransitionStyle.m */,
6491
183B5FB9228DA1220013B58C /* RCTConvert+UIPageViewControllerNavigationOrientation.h */,
@@ -70,6 +97,7 @@
7097
58B511D21A9E6C8500147676 = {
7198
isa = PBXGroup;
7299
children = (
100+
0813B11524A627AC00B13827 /* Events */,
73101
183B5FB5228DA03B0013B58C /* Extension */,
74102
183B5EC9228BEC260013B58C /* ReactNativePageView.h */,
75103
183B5ECA228BEC260013B58C /* ReactNativePageView.m */,
@@ -140,6 +168,10 @@
140168
18A7DC7A228ADDB3006DE42B /* ReactViewPagerManager.m in Sources */,
141169
183B5ECB228BEC260013B58C /* ReactNativePageView.m in Sources */,
142170
183B5FB8228DA0750013B58C /* RCTConvert+UIPageViewControllerTransitionStyle.m in Sources */,
171+
0813B11C24A627BA00B13827 /* RCTOnPageSelected.m in Sources */,
172+
0813B11E24A627BA00B13827 /* RCTOnPageScrollEvent.m in Sources */,
173+
0813B11424A6277400B13827 /* UIViewController+CreateExtension.m in Sources */,
174+
0813B11D24A627BA00B13827 /* RCTOnPageScrollStateChanged.m in Sources */,
143175
);
144176
runOnlyForDeploymentPostprocessing = 0;
145177
};

ios/ReactNativePageView.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,10 @@
55

66
NS_ASSUME_NONNULL_BEGIN
77

8-
@interface ReactNativePageView: UIView <UIPageViewControllerDataSource, UIPageViewControllerDelegate,UIScrollViewDelegate>
8+
@interface ReactNativePageView: UIView
99

1010
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher;
1111

12-
@property(strong, nonatomic, readonly) UIPageViewController *reactPageViewController;
13-
@property(strong, nonatomic, readonly) UIPageControl *reactPageIndicatorView;
14-
@property(nonatomic, readonly) RCTEventDispatcher *eventDispatcher;
15-
16-
@property(nonatomic, strong) NSMutableArray<UIViewController *> *childrenViewControllers;
1712
@property(nonatomic) NSInteger initialPage;
1813
@property(nonatomic) NSInteger currentIndex;
1914
@property(nonatomic) NSInteger pageMargin;
@@ -27,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
2722
@property(nonatomic, copy) RCTDirectEventBlock onPageScrollStateChanged;
2823

2924

30-
- (void)goTo:(NSNumber *)index animated:(BOOL)animated;
25+
- (void)goTo:(NSInteger)index animated:(BOOL)animated;
3126
- (void)shouldScroll:(BOOL)scrollEnabled;
3227
- (void)shouldShowPageIndicator:(BOOL)showPageIndicator;
3328
- (void)shouldDismissKeyboard:(NSString *)dismissKeyboard;

0 commit comments

Comments
 (0)