@@ -25,6 +25,10 @@ @interface RCTWebView () <UIWebViewDelegate, RCTAutoInsetsProtocol>
2525@property (nonatomic , copy ) RCTDirectEventBlock onLoadingStart;
2626@property (nonatomic , copy ) RCTDirectEventBlock onLoadingFinish;
2727@property (nonatomic , copy ) RCTDirectEventBlock onLoadingError;
28+ @property (nonatomic , copy ) RCTDirectEventBlock onShouldStartLoadWithRequest;
29+ @property (nonatomic , strong ) NSConditionLock *conditionLock;
30+ @property (nonatomic , assign ) BOOL startLoadResult;
31+ @property (nonatomic , strong ) NSOperationQueue *operationQueue;
2832
2933@end
3034
@@ -43,6 +47,8 @@ - (instancetype)initWithFrame:(CGRect)frame
4347 _webView = [[UIWebView alloc ] initWithFrame: self .bounds];
4448 _webView.delegate = self;
4549 [self addSubview: _webView];
50+
51+ self.operationQueue = [[NSOperationQueue alloc ] init ];
4652 }
4753 return self;
4854}
@@ -142,6 +148,16 @@ - (void)refreshContentInset
142148- (BOOL )webView : (__unused UIWebView *)webView shouldStartLoadWithRequest : (NSURLRequest *)request
143149 navigationType : (UIWebViewNavigationType)navigationType
144150{
151+ // skip this for the JS Navigation handler
152+ if (![request.URL .scheme isEqualToString: RCTJSNavigationScheme] &&
153+ _onShouldStartLoadWithRequest) {
154+ NSMutableDictionary *event = [self baseEvent ];
155+ [event addEntriesFromDictionary: @{
156+ @" url" : (request.URL ).absoluteString ,
157+ @" navigationType" : @(navigationType)
158+ }];
159+ return [self onShouldStartLoadWithRequest: event];
160+ }
145161 if (_onLoadingStart) {
146162 // We have this check to filter out iframe requests and whatnot
147163 BOOL isTopFrame = [request.URL isEqual: request.mainDocumentURL];
@@ -159,6 +175,34 @@ - (BOOL)webView:(__unused UIWebView *)webView shouldStartLoadWithRequest:(NSURLR
159175 return ![request.URL .scheme isEqualToString: RCTJSNavigationScheme];
160176}
161177
178+ - (BOOL )onShouldStartLoadWithRequest : (NSMutableDictionary *)event {
179+ id observer = [[NSNotificationCenter defaultCenter ] addObserverForName: @" webViewStartLoadNotification" object: nil queue: self .operationQueue usingBlock: ^(NSNotification * _Nonnull note) {
180+ NSDictionary *userInfo = note.userInfo ;
181+
182+ NSInteger lockIdentifier = ((NSNumber *)userInfo[@" lockIdentifier" ]).longValue ;
183+ self.startLoadResult = ((NSNumber *)userInfo[@" result" ]).boolValue ;
184+
185+ [self .conditionLock unlockWithCondition: lockIdentifier];
186+ self.conditionLock = nil ;
187+ }];
188+
189+ NSInteger lockIdentifier = arc4random ();
190+ self.conditionLock = [[NSConditionLock alloc ] initWithCondition: lockIdentifier];
191+ [self .conditionLock lock ];
192+
193+ [event addEntriesFromDictionary: @{
194+ @" lockIdentifier" : @(lockIdentifier)
195+ }];
196+ _onShouldStartLoadWithRequest (event);
197+
198+ [self .conditionLock lockBeforeDate: [NSDate dateWithTimeIntervalSinceNow: 1 ]];
199+
200+ [[NSNotificationCenter defaultCenter ] removeObserver: observer];
201+
202+ return self.startLoadResult ;
203+ }
204+
205+
162206- (void )webView : (__unused UIWebView *)webView didFailLoadWithError : (NSError *)error
163207{
164208 if (_onLoadingError) {
0 commit comments