// DZWebBrowser.m // SimpleWebBrowser // // Created by Ignacio Romero Zurbuchen on 5/25/12. // Copyright (c) 2011 DZen Interaktiv. // Licence: MIT-Licence // #import "DZWebBrowser.h" #import #define kWebLoadingTimout 10.0 @interface DZWebBrowser () { UIBarButtonItem *stopButton; UIBarButtonItem *backButton; UIBarButtonItem *forwardButton; UIBarButtonItem *shareButton; UILabel *_titleLabel; UIActivityIndicatorView *_activityIndicator; UIProgressView *_progressView; NJKWebViewProgress *_progressProxy; } /** */ @property(nonatomic, strong) UIImage *navBarBkgdImage; /** */ @property(nonatomic, strong) UIImage *toolBarBkgdImage; /** */ @property(nonatomic, strong) NSBundle *webControlsBundle; /** */ @property (nonatomic, strong) Reachability *netReach; @end @implementation DZWebBrowser @synthesize webView = _webView; @synthesize navBarBkgdImage = _navBarBkgdImage; @synthesize toolBarBkgdImage = _toolBarBkgdImage; @synthesize currentURL = _currentURL; @synthesize netReach = _netReach; - (id)initWebBrowserWithURL:(NSURL *)URL { self = [super init]; if (self) { _currentURL = URL; //Init Internet Reachability _netReach = [Reachability reachabilityForInternetConnection]; [_netReach startNotifier]; } return self; } #pragma mark - View lifecycle - (void)viewDidLoad { [super viewDidLoad]; _titleLabel = (UILabel *)self.navigationItem.titleView; [self.navigationController.navigationBar setTintColor:[UIColor blackColor]]; [self.navigationController.toolbar setTintColor:[UIColor blackColor]]; [self.navigationController setToolbarHidden:NO]; [self setToolbarItems:self.items animated:NO]; [self.navigationItem setLeftBarButtonItem:self.closeButton animated:NO]; UIBarButtonItem *indicatorButton = [[UIBarButtonItem alloc] initWithCustomView:self.activityIndicator]; [self.navigationItem setRightBarButtonItem:indicatorButton animated:YES]; backButton.enabled = NO; forwardButton.enabled = NO; shareButton.enabled = NO; [self.view addSubview:self.webView]; [_webView loadRequest:[NSURLRequest requestWithURL:_currentURL]]; _progressProxy = [[NJKWebViewProgress alloc] init]; _webView.delegate = _progressProxy; _progressProxy.webViewProxyDelegate = self; _progressProxy.progressDelegate = self; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; } #pragma mark Getter Methods - (UIWebView *)webView { if (!_webView) { _webView = [[UIWebView alloc] initWithFrame:self.view.bounds]; _webView.delegate = self; _webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _webView.scalesPageToFit = YES; if (OS_SUPERIOR_OR_EQUAL_THAN(@"6.0")) { _webView.suppressesIncrementalRendering = YES; } } return _webView; } - (UIActivityIndicatorView *)activityIndicator { if (!_activityIndicator) { _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; _activityIndicator.color = [UIColor whiteColor]; _activityIndicator.hidesWhenStopped = YES; } return _activityIndicator; } - (UIProgressView *)progressView { if (!_progressView) { _progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar]; _progressView.progressTintColor = [UIColor lightGrayColor]; _progressView.trackTintColor = [UIColor darkGrayColor]; [self.navigationItem setTitleView:_progressView]; // CGSize size = self.navigationController.navigationBar.frame.size; // UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width/2, size.height/2)]; // [titleView addSubview:_progressView]; // [self.navigationItem setTitleView:titleView]; } return _progressView; } - (UIBarButtonItem *)closeButton { return [[UIBarButtonItem alloc] initWithTitle:CLOSE_BTN_TITLE style:UIBarButtonItemStyleDone target:self action:@selector(closeAction:)]; } - (NSArray *)items { UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; if (!_webControlsBundle) { NSString *defaultPath = [[NSBundle mainBundle] pathForResource:NSStringFromClass([self class]) ofType:@"bundle"]; _webControlsBundle = [[NSBundle alloc] initWithPath:defaultPath]; } UIImage *stopImg = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"webStopButton" ofType:@"png"]]; UIImage *backImg = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"webPrevButton" ofType:@"png"]]; UIImage *forwardImg = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"webNextButton" ofType:@"png"]]; stopButton = [[UIBarButtonItem alloc] initWithImage:stopImg style:UIBarButtonItemStylePlain target:self action:@selector(stopAction:)]; backButton = [[UIBarButtonItem alloc] initWithImage:backImg style:UIBarButtonItemStylePlain target:self action:@selector(backAction:)]; forwardButton = [[UIBarButtonItem alloc] initWithImage:forwardImg style:UIBarButtonItemStylePlain target:self action:@selector(forwardAction:)]; shareButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(shareAction:)]; return [[NSArray alloc] initWithObjects:space, stopButton, space, backButton, space, forwardButton, space, shareButton, space, nil]; } #pragma mark Setter Methods - (void)setNavBarBkgdImage:(UIImage *)image { [self.navigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault]; } - (void)setToolBarBkgdImage:(UIImage *)image { [self.navigationController.toolbar setBackgroundImage:image forToolbarPosition:UIToolbarPositionBottom barMetrics:UIBarMetricsDefault]; } - (void)setWebControlsBundle:(NSBundle *)bundle { } - (void)showLoadingIndicator:(BOOL)show { [UIApplication sharedApplication].networkActivityIndicatorVisible = show; if (!_showProgress) { if (show) { self.navigationItem.title = LOADING_TITLE; [self.activityIndicator startAnimating]; } else { self.navigationItem.title = [_webView stringByEvaluatingJavaScriptFromString:@"document.title"]; [self.navigationItem setRightBarButtonItem:nil animated:NO]; [self.activityIndicator stopAnimating]; } } } #pragma mark - #pragma mark WebViewController Methods - (void)stopAction:(id)sender { [_webView stopLoading]; [self showLoadingIndicator:NO]; } - (void)backAction:(id)sender { [_webView goBack]; } - (void)forwardAction:(id)sender { [_webView goForward]; } - (void)shareAction:(id)sender { UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:CANCEL_ACTIONSHEET_TITLE destructiveButtonTitle:nil otherButtonTitles:ACTIONSHEET_TWITTER_BTN_TITLE, ACTIONSHEET_FACEBOOK_BTN_TITLE, ACTIONSHEET_MAIL_BTN_TITLE, ACTIONSHEET_COPY_BTN_TITLE, nil]; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { [actionSheet showFromBarButtonItem:sender animated:YES]; } else { [actionSheet showFromToolbar:self.navigationController.toolbar]; } } /** * Renders a graphic context form the browser's webview. * Scale factor and offset are taken in consideration. * * @params view The view from which to render the graphic context. * @returns An image from the graphic context of the specified view. */ - (UIImage *)getThumbnailFromWebView { UIImage *image = nil; UIGraphicsBeginImageContextWithOptions(_webView.frame.size,NO,0.0); { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextTranslateCTM(context, 0, 0); for (UIView *subview in _webView.scrollView.subviews) { [subview.layer renderInContext:context]; //// Renders the viewport snapshot image = UIGraphicsGetImageFromCurrentImageContext(); } } UIGraphicsEndImageContext(); return image; } - (void)closeAction:(id)sender { [self browserWillClose]; [self dismissViewControllerAnimated:YES completion:NULL]; } - (void)browserWillClose { [self showLoadingIndicator:NO]; [_webView stopLoading]; _webView.delegate = nil; _webView = nil; } #pragma mark - #pragma mark UIWebViewDelegate - (BOOL)webView:(UIWebView *)webview shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { //Little timer to avoid loading lags NSTimer *webTimer = [NSTimer timerWithTimeInterval:kWebLoadingTimout target:self selector:@selector(reachabilityChanged) userInfo:nil repeats:NO]; [[NSRunLoop mainRunLoop] addTimer:webTimer forMode:NSDefaultRunLoopMode]; self.currentURL = request.URL; stopButton.enabled = YES; return YES; } - (void)webViewDidStartLoad:(UIWebView *)webview { [self showLoadingIndicator:YES]; } - (void)webViewDidFinishLoad:(UIWebView *)webview { stopButton.enabled = NO; backButton.enabled = [webview canGoBack]; forwardButton.enabled = [webview canGoForward]; shareButton.enabled = YES; [self showLoadingIndicator:NO]; } - (void)webView:(UIWebView *)webview didFailLoadWithError:(NSError *)error { [self webViewDidFinishLoad:webview]; [self showLoadingIndicator:NO]; } #pragma mark - NJKWebViewProgressDelegate -(void)webViewProgress:(NJKWebViewProgress *)webViewProgress updateProgress:(float)progress { [self.progressView setProgress:progress animated:NO]; if (progress == 1.0) { _progressView = nil; self.navigationItem.title = [_webView stringByEvaluatingJavaScriptFromString:@"document.title"]; [self.navigationItem setTitleView:_titleLabel]; } } #pragma mark UIActionSheetDelegate Methods - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { NSString *buttonTitle = [actionSheet buttonTitleAtIndex:buttonIndex]; if ([buttonTitle isEqualToString:ACTIONSHEET_MAIL_BTN_TITLE]) { if ([MFMailComposeViewController canSendMail]) { MFMailComposeViewController *mailComposeVC = [[MFMailComposeViewController alloc] init]; mailComposeVC.mailComposeDelegate = self; mailComposeVC.navigationBar.tintColor = self.navigationController.navigationBar.tintColor; [mailComposeVC setSubject:self.navigationItem.title]; [mailComposeVC setMessageBody:_webView.request.URL.absoluteString isHTML:YES]; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { mailComposeVC.modalPresentationStyle = UIModalPresentationFormSheet; } mailComposeVC.modalPresentationStyle = UIModalPresentationFormSheet; [self.navigationController presentViewController:mailComposeVC animated:YES completion:NULL]; } } else if ([buttonTitle isEqualToString:ACTIONSHEET_COPY_BTN_TITLE]) { UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard]; [pasteBoard setString:_webView.request.URL.absoluteString]; } else { NSString *ServiceType = nil; if ([buttonTitle isEqualToString:ACTIONSHEET_TWITTER_BTN_TITLE]) { if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) { ServiceType = SLServiceTypeTwitter; } } else if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:ACTIONSHEET_FACEBOOK_BTN_TITLE]) { if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) { ServiceType = SLServiceTypeFacebook; } } if (ServiceType) { SLComposeViewController *socialComposeVC = [SLComposeViewController composeViewControllerForServiceType:ServiceType]; [socialComposeVC setInitialText:[NSString stringWithFormat:@"%@\n%@",self.navigationItem.title,_webView.request.URL.absoluteString]]; [socialComposeVC addImage:[self getThumbnailFromWebView]]; [self.navigationController presentViewController:socialComposeVC animated:YES completion:NULL]; } } } #pragma mark MFMailComposeViewControllerDelegate Methods - (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error { [controller dismissViewControllerAnimated:YES completion:NULL]; } #pragma mark - #pragma mark Reachability Notification - (void)reachabilityChanged { if (![self networkReachable]) { [_webView stopLoading]; forwardButton.enabled = NO; shareButton.enabled = NO; UIAlertView *alertNoInternet = [[UIAlertView alloc] initWithTitle:ALERT_NO_INTERNET_TITLE message:ALERT_NO_INTERNET_MESSAGE delegate:nil cancelButtonTitle:ALERT_OK otherButtonTitles:nil]; [alertNoInternet show]; } } - (BOOL)networkReachable { NetworkStatus netStatus = [self.netReach currentReachabilityStatus]; BOOL connectionRequired = [self.netReach connectionRequired]; if (((netStatus == ReachableViaWiFi) || (netStatus == ReachableViaWWAN)) && (!connectionRequired)) { return YES; } return NO; } #pragma mark - View lifeterm - (void)didReceiveMemoryWarning { _webView.delegate = nil; _webView = nil; [super didReceiveMemoryWarning]; } - (void)viewWillUnload { NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil]; [NSURLCache setSharedURLCache:sharedCache]; [sharedCache removeAllCachedResponses]; sharedCache = nil; [super viewWillUnload]; } - (void)viewDidUnload { [super viewDidUnload]; } @end