From 904736c1063b3a05d3d3409779d6f12f20c094a0 Mon Sep 17 00:00:00 2001 From: romulo Date: Fri, 28 Feb 2020 11:38:48 -0300 Subject: [PATCH 1/9] UIWeview -> WKWebview --- Bolts.xcodeproj/project.pbxproj | 13 +++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++ .../xcshareddata/xcschemes/Bolts-iOS.xcscheme | 22 ++--- Bolts/iOS/BFWebViewAppLinkResolver.m | 95 +++++++++++-------- Vendor/xctoolchain | 2 +- 5 files changed, 85 insertions(+), 55 deletions(-) create mode 100644 Bolts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/Bolts.xcodeproj/project.pbxproj b/Bolts.xcodeproj/project.pbxproj index 2f9b1d0a9..f6c27016b 100644 --- a/Bolts.xcodeproj/project.pbxproj +++ b/Bolts.xcodeproj/project.pbxproj @@ -47,6 +47,8 @@ 1EC3017118CDAA8400D06D07 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EC3017018CDAA8400D06D07 /* AppDelegate.m */; }; 1EC3017318CDAA8400D06D07 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1EC3017218CDAA8400D06D07 /* Images.xcassets */; }; 1EC3019118CDABCE00D06D07 /* AppLinkTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EC3019018CDABCE00D06D07 /* AppLinkTests.m */; }; + 46A4AE4424094C690022BB98 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46A4AE4324094C690022BB98 /* WebKit.framework */; }; + 46A4AE4524094DD70022BB98 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46A4AE4324094C690022BB98 /* WebKit.framework */; }; 7C60AEC61ACF19F900747DD7 /* CancellationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C60AEC51ACF19F900747DD7 /* CancellationTests.m */; }; 7C60AEC71ACF19FD00747DD7 /* CancellationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C60AEC51ACF19F900747DD7 /* CancellationTests.m */; }; 7C60AEC81ACF1A0100747DD7 /* BFCancellationToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C60AEBD1ACF08F300747DD7 /* BFCancellationToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -228,6 +230,7 @@ 1EC3017018CDAA8400D06D07 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 1EC3017218CDAA8400D06D07 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 1EC3019018CDABCE00D06D07 /* AppLinkTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppLinkTests.m; sourceTree = ""; }; + 46A4AE4324094C690022BB98 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 7C60AEBD1ACF08F300747DD7 /* BFCancellationToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BFCancellationToken.h; sourceTree = ""; }; 7C60AEBE1ACF08F300747DD7 /* BFCancellationToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BFCancellationToken.m; sourceTree = ""; }; 7C60AEC11ACF093D00747DD7 /* BFCancellationTokenSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BFCancellationTokenSource.h; sourceTree = ""; }; @@ -359,6 +362,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 46A4AE4424094C690022BB98 /* WebKit.framework in Frameworks */, 81ED941B1BE147CF00795F05 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -367,6 +371,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 46A4AE4524094DD70022BB98 /* WebKit.framework in Frameworks */, 818ADC6C1BE1A80F00C8006C /* Bolts.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -606,6 +611,7 @@ 8E9C3CEB17DE9DE000427E62 /* Frameworks */ = { isa = PBXGroup; children = ( + 46A4AE4324094C690022BB98 /* WebKit.framework */, 81D0EE7C19AFA8260000AE75 /* UIKit.framework */, 8E9C3CEC17DE9DE000427E62 /* Foundation.framework */, 8E9C3CFB17DE9DE000427E62 /* SenTestingKit.framework */, @@ -982,6 +988,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 8E9C3CE017DE9DE000427E62; @@ -1374,6 +1381,9 @@ isa = XCBuildConfiguration; baseConfigurationReference = 81D646EA1D2CA0E000690609 /* BoltsTests-iOS.xcconfig */; buildSettings = { + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + VALID_ARCHS = "arm64 arm64e armv7 armv7s"; }; name = Debug; }; @@ -1381,6 +1391,9 @@ isa = XCBuildConfiguration; baseConfigurationReference = 81D646EA1D2CA0E000690609 /* BoltsTests-iOS.xcconfig */; buildSettings = { + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + VALID_ARCHS = "arm64 arm64e armv7 armv7s"; }; name = Release; }; diff --git a/Bolts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Bolts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/Bolts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Bolts.xcodeproj/xcshareddata/xcschemes/Bolts-iOS.xcscheme b/Bolts.xcodeproj/xcshareddata/xcschemes/Bolts-iOS.xcscheme index 98c8ffee2..94ba58a7c 100644 --- a/Bolts.xcodeproj/xcshareddata/xcschemes/Bolts-iOS.xcscheme +++ b/Bolts.xcodeproj/xcshareddata/xcschemes/Bolts-iOS.xcscheme @@ -42,6 +42,15 @@ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES" codeCoverageEnabled = "YES"> + + + + @@ -54,17 +63,6 @@ - - - - - - - - +#import #import "BFWebViewAppLinkResolver.h" #import "BFAppLink.h" @@ -47,41 +47,42 @@ static NSString *const BFWebViewAppLinkResolverWebURLKey = @"url"; static NSString *const BFWebViewAppLinkResolverShouldFallbackKey = @"should_fallback"; -@interface BFWebViewAppLinkResolverWebViewDelegate : NSObject +@interface BFWebViewAppLinkResolverWebViewDelegate : NSObject -@property (nonatomic, copy) void (^didFinishLoad)(UIWebView *webView); -@property (nonatomic, copy) void (^didFailLoadWithError)(UIWebView *webView, NSError *error); +@property (nonatomic, copy) void (^didFinishLoad)(WKWebView *webView); +@property (nonatomic, copy) void (^didFailLoadWithError)(WKWebView *webView, NSError *error); @property (nonatomic, assign) BOOL hasLoaded; @end @implementation BFWebViewAppLinkResolverWebViewDelegate -- (void)webViewDidFinishLoad:(UIWebView *)webView { +- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation { if (self.didFinishLoad) { self.didFinishLoad(webView); } + self.hasLoaded = YES; } -- (void)webViewDidStartLoad:(UIWebView *)webView { +- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation +{ + } -- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { +- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error { if (self.didFailLoadWithError) { self.didFailLoadWithError(webView, error); } } -- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { - if (self.hasLoaded) { - // Consider loading a second resource to be "success", since it indicates an inner frame - // or redirect is happening. We can run the tag extraction script at this point. - self.didFinishLoad(webView); - return NO; - } - self.hasLoaded = YES; - return YES; -} +//- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { +// if (self.hasLoaded) { +// // Consider loading a second resource to be "success", since it indicates an inner frame +// // or redirect is happening. We can run the tag extraction script at this point. +// self.didFinishLoad(webView); +// } +// self.hasLoaded = YES; +//} @end @@ -150,34 +151,41 @@ - (BFTask *)appLinkFromURLInBackground:(NSURL *)url NS_EXTENSION_UNAVAILABLE_IOS NSHTTPURLResponse *response = task.result[@"response"]; BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource]; - UIWebView *webView = [[UIWebView alloc] init]; + WKWebView *webView = [[WKWebView alloc] init]; BFWebViewAppLinkResolverWebViewDelegate *listener = [[BFWebViewAppLinkResolverWebViewDelegate alloc] init]; __block BFWebViewAppLinkResolverWebViewDelegate *retainedListener = listener; - listener.didFinishLoad = ^(UIWebView *view) { + listener.didFinishLoad = ^(WKWebView *view) { if (retainedListener) { - NSDictionary *ogData = [self getALDataFromLoadedPage:view]; - [view removeFromSuperview]; - view.delegate = nil; - retainedListener = nil; - [tcs setResult:[self appLinkFromALData:ogData destination:url]]; + [self getALDataFromLoadedPage:view completion:^(NSDictionary *result, NSError *error) { + [view removeFromSuperview]; + view.navigationDelegate = nil; + retainedListener = nil; + [tcs setResult:[self appLinkFromALData:result destination:url]]; + }]; } }; - listener.didFailLoadWithError = ^(UIWebView* view, NSError *error) { + listener.didFailLoadWithError = ^(WKWebView* view, NSError *error) { if (retainedListener) { [view removeFromSuperview]; - view.delegate = nil; + view.navigationDelegate = nil; retainedListener = nil; [tcs setError:error]; } }; - webView.delegate = listener; + webView.navigationDelegate = listener; + webView.configuration.preferences.javaScriptEnabled = true; webView.hidden = YES; - [webView loadData:responseData - MIMEType:response.MIMEType - textEncodingName:response.textEncodingName - baseURL:response.URL]; - UIWindow *window = [UIApplication sharedApplication].windows.firstObject; - [window addSubview:webView]; + if (@available(iOS 9.0, *)) { + [webView loadData:responseData + MIMEType:response.MIMEType + characterEncodingName:response.textEncodingName + baseURL:response.URL]; + + UIWindow *window = [UIApplication sharedApplication].windows.firstObject; + [window addSubview:webView]; + } else { + // Fallback on earlier versions + } return tcs.task; }]; @@ -220,14 +228,19 @@ - (NSDictionary *)parseALData:(NSArray *)dataArray { return al; } -- (NSDictionary *)getALDataFromLoadedPage:(UIWebView *)webView { - // Run some JavaScript in the webview to fetch the meta tags. - NSString *jsonString = [webView stringByEvaluatingJavaScriptFromString:BFWebViewAppLinkResolverTagExtractionJavaScript]; - NSError *error = nil; - NSArray *arr = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] - options:0 - error:&error]; - return [self parseALData:arr]; +- (void)getALDataFromLoadedPage:(WKWebView *)webView completion:(void (^ _Nullable)(NSDictionary * _Nullable, NSError * _Nullable error))completionHandler { + [webView evaluateJavaScript:BFWebViewAppLinkResolverTagExtractionJavaScript completionHandler:^(id result, NSError * error) { + if (error == nil) { + NSString *jsonString = result; + NSError *parseError = nil; + NSArray *arr = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] + options:0 + error:&parseError]; + completionHandler([self parseALData:arr], parseError); + } else { + completionHandler(nil, error); + } + }]; } /* diff --git a/Vendor/xctoolchain b/Vendor/xctoolchain index e28a967bb..f5e550393 160000 --- a/Vendor/xctoolchain +++ b/Vendor/xctoolchain @@ -1 +1 @@ -Subproject commit e28a967bba339b6e157f6d2d2426ed5b2c760107 +Subproject commit f5e550393cff86ed780b16a59f43b496daf4c341 From 3d36fcfe3e7d94a2dcd8c442ffe4d02a22236cba Mon Sep 17 00:00:00 2001 From: romulo Date: Fri, 28 Feb 2020 12:04:14 -0300 Subject: [PATCH 2/9] This is a straight forward migration to WKWebview --- Bolts/iOS/BFWebViewAppLinkResolver.m | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Bolts/iOS/BFWebViewAppLinkResolver.m b/Bolts/iOS/BFWebViewAppLinkResolver.m index adbbbe51c..bf2f72f30 100644 --- a/Bolts/iOS/BFWebViewAppLinkResolver.m +++ b/Bolts/iOS/BFWebViewAppLinkResolver.m @@ -75,14 +75,16 @@ - (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavig } } -//- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { -// if (self.hasLoaded) { -// // Consider loading a second resource to be "success", since it indicates an inner frame -// // or redirect is happening. We can run the tag extraction script at this point. -// self.didFinishLoad(webView); -// } -// self.hasLoaded = YES; -//} +- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { + if (self.hasLoaded) { + // Consider loading a second resource to be "success", since it indicates an inner frame + // or redirect is happening. We can run the tag extraction script at this point. + self.didFinishLoad(webView); + } + self.hasLoaded = YES; + + decisionHandler(WKNavigationActionPolicyAllow); +} @end From d3557b3ee7f50df106cf86f10f4ed8c21b9dae45 Mon Sep 17 00:00:00 2001 From: romulo Date: Fri, 28 Feb 2020 12:13:43 -0300 Subject: [PATCH 3/9] It's the final code --- Bolts/iOS/BFWebViewAppLinkResolver.m | 1 - 1 file changed, 1 deletion(-) diff --git a/Bolts/iOS/BFWebViewAppLinkResolver.m b/Bolts/iOS/BFWebViewAppLinkResolver.m index bf2f72f30..a862b7ff9 100644 --- a/Bolts/iOS/BFWebViewAppLinkResolver.m +++ b/Bolts/iOS/BFWebViewAppLinkResolver.m @@ -61,7 +61,6 @@ - (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNav if (self.didFinishLoad) { self.didFinishLoad(webView); } - self.hasLoaded = YES; } - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation From ba28d4c5c751c390150bc957a54b7e906d1765c1 Mon Sep 17 00:00:00 2001 From: romulo Date: Fri, 28 Feb 2020 13:07:10 -0300 Subject: [PATCH 4/9] fix build using carthage --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fe716a075..f202ec497 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ branches: - master language: objective-c os: osx -osx_image: xcode9.2 +osx_image: xcode11.3 cache: - cocoapods env: From cbe0253b25425d56323a95b30bf33bf77445d367 Mon Sep 17 00:00:00 2001 From: romulo Date: Fri, 28 Feb 2020 13:12:52 -0300 Subject: [PATCH 5/9] fix build using carthage (second try) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f202ec497..d07882226 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ branches: - master language: objective-c os: osx -osx_image: xcode11.3 +osx_image: xcode10 cache: - cocoapods env: From 42463a52c3672f8aeaf99b67e1a860508e5714db Mon Sep 17 00:00:00 2001 From: romulo Date: Fri, 28 Feb 2020 13:22:01 -0300 Subject: [PATCH 6/9] fix build using carthage (third try) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d07882226..ef42d21d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,9 +16,9 @@ env: before_install: - | if [ "$TEST_TYPE" = iOS ] || [ "$TEST_TYPE" = macOS ] || [ "$TEST_TYPE" = tvOS ]; then - gem install xcpretty -N --no-ri --no-rdoc + gem install xcpretty -N --no-document elif [ "$TEST_TYPE" = CocoaPods ]; then - gem install cocoapods --pre --quiet --no-ri --no-rdoc + gem install cocoapods --pre --no-document elif [ "$TEST_TYPE" = Carthage ]; then brew update brew install carthage || brew upgrade carthage From d75e2b8d74a68ae0937cd28789e0bdb7f8322285 Mon Sep 17 00:00:00 2001 From: romulo Date: Fri, 28 Feb 2020 13:38:55 -0300 Subject: [PATCH 7/9] fix Bolts-iOS-Dynamic build for carthage --- Bolts.xcodeproj/project.pbxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Bolts.xcodeproj/project.pbxproj b/Bolts.xcodeproj/project.pbxproj index f6c27016b..94a1f815e 100644 --- a/Bolts.xcodeproj/project.pbxproj +++ b/Bolts.xcodeproj/project.pbxproj @@ -49,6 +49,7 @@ 1EC3019118CDABCE00D06D07 /* AppLinkTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EC3019018CDABCE00D06D07 /* AppLinkTests.m */; }; 46A4AE4424094C690022BB98 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46A4AE4324094C690022BB98 /* WebKit.framework */; }; 46A4AE4524094DD70022BB98 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46A4AE4324094C690022BB98 /* WebKit.framework */; }; + 46D245272409796A00AB92BE /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46A4AE4324094C690022BB98 /* WebKit.framework */; }; 7C60AEC61ACF19F900747DD7 /* CancellationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C60AEC51ACF19F900747DD7 /* CancellationTests.m */; }; 7C60AEC71ACF19FD00747DD7 /* CancellationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C60AEC51ACF19F900747DD7 /* CancellationTests.m */; }; 7C60AEC81ACF1A0100747DD7 /* BFCancellationToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C60AEBD1ACF08F300747DD7 /* BFCancellationToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -320,6 +321,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 46D245272409796A00AB92BE /* WebKit.framework in Frameworks */, 1D5D7DB81BE3CE8200FD67C7 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; From 68fad5a22a377092bf93923a93c4ed64019040e0 Mon Sep 17 00:00:00 2001 From: romulo Date: Mon, 16 Mar 2020 09:07:57 -0300 Subject: [PATCH 8/9] it's just a cosmetic improvement --- Bolts/iOS/BFWebViewAppLinkResolver.h | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Bolts/iOS/BFWebViewAppLinkResolver.h b/Bolts/iOS/BFWebViewAppLinkResolver.h index 3782ae2cb..c9e389c23 100644 --- a/Bolts/iOS/BFWebViewAppLinkResolver.h +++ b/Bolts/iOS/BFWebViewAppLinkResolver.h @@ -13,7 +13,7 @@ #import /*! - A reference implementation for an App Link resolver that uses a hidden UIWebView + A reference implementation for an App Link resolver that uses a hidden WKWebView to parse the HTML containing App Link metadata. */ @interface BFWebViewAppLinkResolver : NSObject diff --git a/README.md b/README.md index 5e972c850..a6bda7bb1 100644 --- a/README.md +++ b/README.md @@ -582,7 +582,7 @@ NSError *error = nil; ### Resolving App Link Metadata -Bolts allows for custom App Link resolution, which may be used as a performance optimization (e.g. caching the metadata) or as a mechanism to allow developers to use a centralized index for obtaining App Link metadata. A custom App Link resolver just needs to be able to take a URL and return a `BFAppLink` containing the ordered list of `BFAppLinkTarget`s that are applicable for this device. Bolts provides one of these out of the box that performs this resolution on the device using a hidden UIWebView. +Bolts allows for custom App Link resolution, which may be used as a performance optimization (e.g. caching the metadata) or as a mechanism to allow developers to use a centralized index for obtaining App Link metadata. A custom App Link resolver just needs to be able to take a URL and return a `BFAppLink` containing the ordered list of `BFAppLinkTarget`s that are applicable for this device. Bolts provides one of these out of the box that performs this resolution on the device using a hidden ~~UIWebView~~ WKWebview. You can use any resolver that implements the `BFAppLinkResolving` protocol by using one of the overloads on `BFAppLinkNavigation`: From 3122920f097d94e3d65bda41f32970f00a6795f4 Mon Sep 17 00:00:00 2001 From: romulo Date: Mon, 16 Mar 2020 09:41:23 -0300 Subject: [PATCH 9/9] It forces Travis CI to run again --- Bolts/iOS/BFWebViewAppLinkResolver.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Bolts/iOS/BFWebViewAppLinkResolver.h b/Bolts/iOS/BFWebViewAppLinkResolver.h index c9e389c23..d46f5a0f7 100644 --- a/Bolts/iOS/BFWebViewAppLinkResolver.h +++ b/Bolts/iOS/BFWebViewAppLinkResolver.h @@ -24,3 +24,4 @@ + (instancetype)sharedInstance; @end +