diff --git a/ExampleProject/KINWebBrowserExample/KINWebBrowserExampleViewController.m b/ExampleProject/KINWebBrowserExample/KINWebBrowserExampleViewController.m index 910f10d..da67f56 100644 --- a/ExampleProject/KINWebBrowserExample/KINWebBrowserExampleViewController.m +++ b/ExampleProject/KINWebBrowserExample/KINWebBrowserExampleViewController.m @@ -38,7 +38,7 @@ @interface KINWebBrowserExampleViewController () @end -static NSString *const defaultAddress = @"http://www.apple.com/"; +static NSString *const defaultAddress = @"https://www.apple.com"; @implementation KINWebBrowserExampleViewController @@ -87,6 +87,11 @@ - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didFailToLoadURL:(N NSLog(@"Failed To Load URL : %@ With Error: %@", URL, error); } +- (void)webBrowserViewControllerWillDismiss:(KINWebBrowserViewController*)viewController { + NSLog(@"View Controller will dismiss: %@", viewController); + +} + #pragma mark - IBActions diff --git a/ExampleProject/Podfile b/ExampleProject/Podfile index 8b6339e..063e61b 100644 --- a/ExampleProject/Podfile +++ b/ExampleProject/Podfile @@ -3,4 +3,5 @@ source 'https://github.com/CocoaPods/Specs.git' xcodeproj 'KINWebBrowserExample.xcodeproj' platform :ios, :deployment_target => '7.0' -pod 'KINWebBrowser', '~> 1.1' +pod 'KINWebBrowser' + diff --git a/KINWebBrowser.podspec b/KINWebBrowser.podspec index 9792a09..95d971d 100644 --- a/KINWebBrowser.podspec +++ b/KINWebBrowser.podspec @@ -2,8 +2,7 @@ Pod::Spec.new do |s| s.name = "KINWebBrowser" - - s.version = "1.1.0" + s.version = "1.3.2" s.summary = "A web browser module for your apps." s.description = <<-DESC KINWebBrowser is a web browser module for your apps. Powered by WKWebView on iOS 8. Backwards compatible with iOS 7 using UIWebView. KINWebBrowser offers the simplest way to add a web browser to your apps. @@ -20,7 +19,7 @@ Pod::Spec.new do |s| s.weak_framework = 'WebKit' - s.dependency 'TUSafariActivity', '1.0.2' - s.dependency 'ARChromeActivity', '1.0.2' + s.dependency 'TUSafariActivity', '1.0.4' + s.dependency 'ARChromeActivity', '1.0.5' -end \ No newline at end of file +end diff --git a/KINWebBrowser/KINWebBrowserViewController.h b/KINWebBrowser/KINWebBrowserViewController.h index fe1af16..64a5087 100644 --- a/KINWebBrowser/KINWebBrowserViewController.h +++ b/KINWebBrowser/KINWebBrowserViewController.h @@ -54,6 +54,7 @@ - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didStartLoadingURL:(NSURL *)URL; - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didFinishLoadingURL:(NSURL *)URL; - (void)webBrowser:(KINWebBrowserViewController *)webBrowser didFailToLoadURL:(NSURL *)URL error:(NSError *)error; +- (void)webBrowserViewControllerWillDismiss:(KINWebBrowserViewController*)viewController; @end @@ -63,7 +64,7 @@ For convenience, two sets of static initializers are available. */ -@interface KINWebBrowserViewController : UIViewController +@interface KINWebBrowserViewController : UIViewController #pragma mark - Public Properties @@ -104,22 +105,35 @@ + (UINavigationController *)navigationControllerWithWebBrowserWithConfiguration:(WKWebViewConfiguration *)configuration NS_AVAILABLE_IOS(8_0); - +@property (nonatomic, strong) UIBarButtonItem *actionButton; @property (nonatomic, strong) UIColor *tintColor; @property (nonatomic, strong) UIColor *barTintColor; @property (nonatomic, assign) BOOL actionButtonHidden; @property (nonatomic, assign) BOOL showsURLInNavigationBar; @property (nonatomic, assign) BOOL showsPageTitleInNavigationBar; +//Allow for custom activities in the browser by populating this optional array +@property (nonatomic, strong) NSArray *customActivityItems; + #pragma mark - Public Interface -// Load a NSURL to webView + +// Load a NSURLURLRequest to web view +// Can be called any time after initialization +- (void)loadRequest:(NSURLRequest *)request; + +// Load a NSURL to web view // Can be called any time after initialization - (void)loadURL:(NSURL *)URL; -// Loads a URL as NSString to webView +// Loads a URL as NSString to web view // Can be called any time after initialization - (void)loadURLString:(NSString *)URLString; + +// Loads an string containing HTML to web view +// Can be called any time after initialization +- (void)loadHTMLString:(NSString *)HTMLString; + @end diff --git a/KINWebBrowser/KINWebBrowserViewController.m b/KINWebBrowser/KINWebBrowserViewController.m index a5e91fe..5355114 100644 --- a/KINWebBrowser/KINWebBrowserViewController.m +++ b/KINWebBrowser/KINWebBrowserViewController.m @@ -32,19 +32,21 @@ #import "KINWebBrowserViewController.h" -#import -#import +#import "TUSafariActivity.h" +#import "ARChromeActivity.h" -static void *KINContext = &KINContext; +static void *KINWebBrowserContext = &KINWebBrowserContext; -@interface KINWebBrowserViewController () +@interface KINWebBrowserViewController () @property (nonatomic, assign) BOOL previousNavigationControllerToolbarHidden, previousNavigationControllerNavigationBarHidden; -@property (nonatomic, strong) UIBarButtonItem *backButton, *forwardButton, *refreshButton, *stopButton, *actionButton, *fixedSeparator, *flexibleSeparator; +@property (nonatomic, strong) UIBarButtonItem *backButton, *forwardButton, *refreshButton, *stopButton, *fixedSeparator, *flexibleSeparator; @property (nonatomic, strong) NSTimer *fakeProgressTimer; @property (nonatomic, strong) UIPopoverController *actionPopoverController; @property (nonatomic, assign) BOOL uiWebViewIsLoading; @property (nonatomic, strong) NSURL *uiWebViewCurrentURL; +@property (nonatomic, strong) NSURL *URLToLaunchWithPermission; +@property (nonatomic, strong) UIAlertView *externalAppPermissionAlertView; @end @@ -58,17 +60,17 @@ + (KINWebBrowserViewController *)webBrowser { } + (KINWebBrowserViewController *)webBrowserWithConfiguration:(WKWebViewConfiguration *)configuration { - KINWebBrowserViewController *webBrowserViewController = [[KINWebBrowserViewController alloc] initWithConfiguration:configuration]; + KINWebBrowserViewController *webBrowserViewController = [[self alloc] initWithConfiguration:configuration]; return webBrowserViewController; } + (UINavigationController *)navigationControllerWithWebBrowser { - KINWebBrowserViewController *webBrowserViewController = [[KINWebBrowserViewController alloc] initWithConfiguration:nil]; + KINWebBrowserViewController *webBrowserViewController = [[self alloc] initWithConfiguration:nil]; return [KINWebBrowserViewController navigationControllerWithBrowser:webBrowserViewController]; } + (UINavigationController *)navigationControllerWithWebBrowserWithConfiguration:(WKWebViewConfiguration *)configuration { - KINWebBrowserViewController *webBrowserViewController = [[KINWebBrowserViewController alloc] initWithConfiguration:configuration]; + KINWebBrowserViewController *webBrowserViewController = [[self alloc] initWithConfiguration:configuration]; return [KINWebBrowserViewController navigationControllerWithBrowser:webBrowserViewController]; } @@ -89,7 +91,6 @@ - (id)init { - (id)initWithConfiguration:(WKWebViewConfiguration *)configuration { self = [super init]; if(self) { - if([WKWebView class]) { if(configuration) { self.wkWebView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration]; @@ -106,6 +107,8 @@ - (id)initWithConfiguration:(WKWebViewConfiguration *)configuration { self.showsURLInNavigationBar = NO; self.showsPageTitleInNavigationBar = YES; + self.externalAppPermissionAlertView = [[UIAlertView alloc] initWithTitle:@"Leave this app?" message:@"This web page is trying to open an outside app. Are you sure you want to open it?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Open App", nil]; + } return self; } @@ -122,12 +125,13 @@ - (void)viewDidLoad { [self.wkWebView setFrame:self.view.bounds]; [self.wkWebView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; [self.wkWebView setNavigationDelegate:self]; + [self.wkWebView setUIDelegate:self]; [self.wkWebView setMultipleTouchEnabled:YES]; [self.wkWebView setAutoresizesSubviews:YES]; [self.wkWebView.scrollView setAlwaysBounceVertical:YES]; [self.view addSubview:self.wkWebView]; - [self.wkWebView addObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress)) options:0 context:KINContext]; + [self.wkWebView addObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress)) options:0 context:KINWebBrowserContext]; } else if(self.uiWebView) { [self.uiWebView setFrame:self.view.bounds]; @@ -171,20 +175,33 @@ - (void)viewWillDisappear:(BOOL)animated { #pragma mark - Public Interface -- (void)loadURL:(NSURL *)URL { +- (void)loadRequest:(NSURLRequest *)request { if(self.wkWebView) { - [self.wkWebView loadRequest:[NSURLRequest requestWithURL:URL]]; + [self.wkWebView loadRequest:request]; } else if(self.uiWebView) { - [self.uiWebView loadRequest:[NSURLRequest requestWithURL:URL]]; + [self.uiWebView loadRequest:request]; } } +- (void)loadURL:(NSURL *)URL { + [self loadRequest:[NSURLRequest requestWithURL:URL]]; +} + - (void)loadURLString:(NSString *)URLString { NSURL *URL = [NSURL URLWithString:URLString]; [self loadURL:URL]; } +- (void)loadHTMLString:(NSString *)HTMLString { + if(self.wkWebView) { + [self.wkWebView loadHTMLString:HTMLString baseURL:nil]; + } + else if(self.uiWebView) { + [self.uiWebView loadHTMLString:HTMLString baseURL:nil]; + } +} + - (void)setTintColor:(UIColor *)tintColor { _tintColor = tintColor; [self.progressView setTintColor:tintColor]; @@ -208,17 +225,25 @@ - (void)setActionButtonHidden:(BOOL)actionButtonHidden { - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { if(webView == self.uiWebView) { - self.uiWebViewCurrentURL = request.URL; - self.uiWebViewIsLoading = YES; - [self updateToolbarState]; - - [self fakeProgressViewStartLoading]; - if([self.delegate respondsToSelector:@selector(webBrowser:didStartLoadingURL:)]) { - [self.delegate webBrowser:self didStartLoadingURL:request.URL]; + if(![self externalAppRequiredToOpenURL:request.URL]) { + self.uiWebViewCurrentURL = request.URL; + self.uiWebViewIsLoading = YES; + [self updateToolbarState]; + + [self fakeProgressViewStartLoading]; + + if([self.delegate respondsToSelector:@selector(webBrowser:didStartLoadingURL:)]) { + [self.delegate webBrowser:self didStartLoadingURL:request.URL]; + } + return YES; + } + else { + [self launchExternalAppWithURL:request.URL]; + return NO; } } - return YES; + return NO; } - (void)webViewDidFinishLoad:(UIWebView *)webView { @@ -290,6 +315,35 @@ - (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigatio } } +- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { + if(webView == self.wkWebView) { + + NSURL *URL = navigationAction.request.URL; + if(![self externalAppRequiredToOpenURL:URL]) { + if(!navigationAction.targetFrame) { + [self loadURL:URL]; + decisionHandler(WKNavigationActionPolicyCancel); + return; + } + } + else if([[UIApplication sharedApplication] canOpenURL:URL]) { + [self launchExternalAppWithURL:URL]; + decisionHandler(WKNavigationActionPolicyCancel); + return; + } + } + decisionHandler(WKNavigationActionPolicyAllow); +} + +#pragma mark - WKUIDelegate + +- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{ + if (!navigationAction.targetFrame.isMainFrame) { + [webView loadRequest:navigationAction.request]; + } + return nil; +} + #pragma mark - Toolbar State - (void)updateToolbarState { @@ -343,13 +397,24 @@ - (void)updateToolbarState { } [self setToolbarItems:barButtonItems animated:YES]; + + self.tintColor = self.tintColor; + self.barTintColor = self.barTintColor; + + } - (void)setupToolbarItems { + NSBundle *bundle = [NSBundle bundleForClass:[KINWebBrowserViewController class]]; + self.refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshButtonPressed:)]; self.stopButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self action:@selector(stopButtonPressed:)]; - self.backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"backbutton"] style:UIBarButtonItemStylePlain target:self action:@selector(backButtonPressed:)]; - self.forwardButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"forwardbutton"] style:UIBarButtonItemStylePlain target:self action:@selector(forwardButtonPressed:)]; + + UIImage *backbuttonImage = [UIImage imageWithContentsOfFile: [bundle pathForResource:@"backbutton" ofType:@"png"]]; + self.backButton = [[UIBarButtonItem alloc] initWithImage:backbuttonImage style:UIBarButtonItemStylePlain target:self action:@selector(backButtonPressed:)]; + + UIImage *forwardbuttonImage = [UIImage imageWithContentsOfFile: [bundle pathForResource:@"forwardbutton" ofType:@"png"]]; + self.forwardButton = [[UIBarButtonItem alloc] initWithImage:forwardbuttonImage style:UIBarButtonItemStylePlain target:self action:@selector(forwardButtonPressed:)]; self.actionButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(actionButtonPressed:)]; self.fixedSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; self.fixedSeparator.width = 50.0f; @@ -407,27 +472,41 @@ - (void)stopButtonPressed:(id)sender { - (void)actionButtonPressed:(id)sender { NSURL *URLForActivityItem; + NSString *URLTitle; if(self.wkWebView) { URLForActivityItem = self.wkWebView.URL; + URLTitle = self.wkWebView.title; } else if(self.uiWebView) { URLForActivityItem = self.uiWebView.request.URL; + URLTitle = [self.uiWebView stringByEvaluatingJavaScriptFromString:@"document.title"]; } - dispatch_async(dispatch_get_main_queue(), ^{ - TUSafariActivity *safariActivity = [[TUSafariActivity alloc] init]; - ARChromeActivity *chromeActivity = [[ARChromeActivity alloc] init]; - UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:@[URLForActivityItem] applicationActivities:@[safariActivity, chromeActivity]]; - if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - if(self.actionPopoverController) { - [self.actionPopoverController dismissPopoverAnimated:YES]; + if (URLForActivityItem) { + dispatch_async(dispatch_get_main_queue(), ^{ + TUSafariActivity *safariActivity = [[TUSafariActivity alloc] init]; + ARChromeActivity *chromeActivity = [[ARChromeActivity alloc] init]; + + NSMutableArray *activities = [[NSMutableArray alloc] init]; + [activities addObject:safariActivity]; + [activities addObject:chromeActivity]; + if(self.customActivityItems != nil) { + [activities addObjectsFromArray:self.customActivityItems]; } - self.actionPopoverController = [[UIPopoverController alloc] initWithContentViewController:controller]; - [self.actionPopoverController presentPopoverFromBarButtonItem:self.actionButton permittedArrowDirections: UIPopoverArrowDirectionAny animated:YES]; - } - else { - [self presentViewController:controller animated:YES completion:NULL]; - } - }); + + UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:@[URLForActivityItem] applicationActivities:activities]; + + if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { + if(self.actionPopoverController) { + [self.actionPopoverController dismissPopoverAnimated:YES]; + } + self.actionPopoverController = [[UIPopoverController alloc] initWithContentViewController:controller]; + [self.actionPopoverController presentPopoverFromBarButtonItem:self.actionButton permittedArrowDirections: UIPopoverArrowDirectionAny animated:YES]; + } + else { + [self presentViewController:controller animated:YES completion:NULL]; + } + }); + } } @@ -490,15 +569,44 @@ - (void)fakeProgressTimerDidFire:(id)sender { } } +#pragma mark - External App Support + +- (BOOL)externalAppRequiredToOpenURL:(NSURL *)URL { + NSSet *validSchemes = [NSSet setWithArray:@[@"http", @"https"]]; + return ![validSchemes containsObject:URL.scheme]; +} + +- (void)launchExternalAppWithURL:(NSURL *)URL { + self.URLToLaunchWithPermission = URL; + if (![self.externalAppPermissionAlertView isVisible]) { + [self.externalAppPermissionAlertView show]; + } + +} + +#pragma mark - UIAlertViewDelegate + +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { + if(alertView == self.externalAppPermissionAlertView) { + if(buttonIndex != alertView.cancelButtonIndex) { + [[UIApplication sharedApplication] openURL:self.URLToLaunchWithPermission]; + } + self.URLToLaunchWithPermission = nil; + } +} + #pragma mark - Dismiss - (void)dismissAnimated:(BOOL)animated { + if([self.delegate respondsToSelector:@selector(webBrowserViewControllerWillDismiss:)]) { + [self.delegate webBrowserViewControllerWillDismiss:self]; + } [self.navigationController dismissViewControllerAnimated:animated completion:nil]; } #pragma mark - Interface Orientation -- (NSUInteger)supportedInterfaceOrientations { +- (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskAllButUpsideDown; } diff --git a/README.md b/README.md index a1cf578..573f037 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ KINWebBrowserViewController *webBrowser = [webBrowserNavigationController rootWe Installation ------------------------ -#### Cocoapods +#### CocoaPods [CocoaPods](http://cocoapods.org) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries in your projects. See the ["Getting Started" for more information](http://guides.cocoapods.org/using/getting-started.html). ###### Podfile