My cordova library was old and had to update it because of iOS11. I have updated it to latest version 4.4.0. CDVViewController is totally different now which enables webviewEngine that takes UIWebview or WKWebview. How do I initiate Cordova webview in my native app. Previously, I loaded it like this -
- (void) viewDidLoad {
[super viewDidLoad];
CDVViewController *viewController = [CDVViewController new];
viewController.wwwFolderName = #"www";
viewController.startPage = #"blank.html";
viewController.view.frame = self.webView.frame;
[self.webView removeFromSuperview];
self.webView = nil;
[self.view addSubview:viewController.view];
self.webView = viewController.webView;
viewController.webView.delegate = self;
self.cordovaWebViewController = viewController;
self.webView.scalesPageToFit = YES;
if (self.url)
[self.webView loadRequest: [NSURLRequest requestWithURL: self.url]];
}
And used webview delegates as
#pragma mark Webview Delegate
- (void) webViewDidStartLoad: (UIWebView *) webViewLocal {
[self.spinner startAnimating];
[self.cordovaWebViewController webViewDidStartLoad:webViewLocal];
}
- (void) webViewDidFinishLoad: (UIWebView *) webViewLocal {
[self.spinner stopAnimating];
[self.cordovaWebViewController webViewDidFinishLoad:webViewLocal];
}
- (void) webView: (UIWebView *) webView didFailLoadWithError: (NSError *) error {
[self.spinner stopAnimating];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
if ([request.URL.absoluteString hasSuffix: #"link_restart_movie_file"]) {
[self loadItem];
return NO;
}
[self.webView loadRequest: request];
return NO;
}
[self.cordovaWebViewController webView:self.webView shouldStartLoadWithRequest:request navigationType:navigationType];
return YES;
}
How do I use WebviewEngine to load in my viewcontroller? Is there any tutorial, that explains the usage of CDVViewController? Please help! Thanks!
Related
I have a Webview with inline URL links which are opened with SFSafariViewController, as shown below:
-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ( inType == UIWebViewNavigationTypeLinkClicked ) {
if ([SFSafariViewController class] != nil) {
NSString *inR = [[inRequest URL] absoluteString];
NSURL *inReq = [NSURL URLWithString:inR];
SFSafariViewController *safariVC = [[SFSafariViewController alloc] initWithURL:inReq entersReaderIfAvailable:YES];
safariVC.delegate = self;
[self presentViewController:safariVC animated:YES completion:nil];
} else {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
}
return YES;
}
#pragma mark - SFSafariViewController delegate methods
-(void)safariViewController:(SFSafariViewController *)controller didCompleteInitialLoad:(BOOL)didLoadSuccessfully {
// Load finished
}
-(void)safariViewControllerDidFinish:(SFSafariViewController *)controller {
// Done button pressed
NSLog(#"DONE PRESSED!!!");
}
When I press the DONE button correctly returns to my Webview. The problem is that if I will press again on the same inline link, it does not open with SFSafariViewController but in Webview which is not what i desire. I tried to force Webview reload in safariViewControllerDidFinish but without success.
Could you please help? Thanks!
The code corrected as below (following proposal of beyowulf) and now is working OK:
-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ( inType == UIWebViewNavigationTypeLinkClicked ) {
if ([SFSafariViewController class] != nil) {
NSString *inR = [[inRequest URL] absoluteString];
NSURL *inReq = [NSURL URLWithString:inR];
SFSafariViewController *safariVC = [[SFSafariViewController alloc] initWithURL:inReq entersReaderIfAvailable:YES];
safariVC.delegate = self;
[self presentViewController:safariVC animated:YES completion:nil];
return NO;
} else {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
} else {
return YES;
}
}
#pragma mark - SFSafariViewController delegate methods
-(void)safariViewController:(SFSafariViewController *)controller didCompleteInitialLoad:(BOOL)didLoadSuccessfully {
// Load finished
}
-(void)safariViewControllerDidFinish:(SFSafariViewController *)controller {
// Done button pressed
NSLog(#"DONE PRESSED!!!");
}
When I'm loading a HTML page that contains ModalDialog in WebView,no popup window is opened at all.That same HTML page works without issue in Safari.So anyone can solve it?
Here is the code:
- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request{
NSWindow *window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 400, 300) styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask backing:NSBackingStoreBuffered defer:YES];
[window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
WebView *webView = [[WebView alloc] init];
[webView setFrameLoadDelegate:self];
window.contentView = webView;
[webView.mainFrame loadRequest:request];
[window makeKeyAndOrderFront:webView];
return webView;
}
- (WebView *)webView:(WebView *)sender createWebViewModalDialogWithRequest:(NSURLRequest *)request{
return [self webView:sender createWebViewWithRequest:request];
}
- (void)webViewRunModal:(WebView *)sender{
[sender.window makeKeyAndOrderFront:sender];
}
- (void)webViewShow:(WebView *)sender{
[sender.window makeKeyAndOrderFront:sender];
}
- (void)webViewClose:(WebView *)sender{
[sender.window close];
}
#pragma -mark -WebView Delegate
- (WebView *)webView:(WebView *)sender createWebViewWithRequest: (NSURLRequest *)request{
NSUInteger windowStyleMask = NSClosableWindowMask|NSMiniaturizableWindowMask|NSTitledWindowMask;
_webWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 400, 300) styleMask:windowStyleMask backing:NSBackingStoreNonretained defer:YES];
[_webWindow setReleasedWhenClosed:NO];
WebView* newWebView = [[WebView alloc] initWithFrame:[_webWindow contentRectForFrameRect:_webWindow.frame]];
[newWebView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
[[newWebView mainFrame] loadRequest:request];
[_webWindow setContentView:newWebView];
[_webWindow center];
[_webWindow makeKeyAndOrderFront:nil];
return newWebView;
}
- (WebView *)webView:(WebView *)sender createWebViewModalDialogWithRequest:(NSURLRequest *)request{
return [self webView:sender createWebViewWithRequest:request];
}
- (void)webViewRunModal:(WebView *)sender{
[sender.window makeKeyAndOrderFront:self];
}
- (void)webViewShow:(WebView *)sender{
[sender.window makeKeyAndOrderFront:self];
}
- (void)webViewClose:(WebView *)sender{
[sender.window close];
}
I am using the below to add a ProgressView while the UIWebView is loading and dismissing it when it's done.
The problem is the UIWebView is started twice and also the ProgressView, So when the page is done loading only one ProgressView is dismissed and the other one doesn't.
ViewController.h
#import <UIKit/UIKit.h>
#interface DirectionViewController : UIViewController <UIWebViewDelegate>
#property (weak, nonatomic) IBOutlet UIWebView *directionWebView;
#end
ViewController.m
#interface ViewController ()
#property UIColor *yellowColor;
#property MRProgressOverlayView *progressView;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.yellowColor =
[UIColor colorWithRed:244.0f/255.0f
green:208.0f/255.0f
blue:63.0f/255.0f
alpha:1.0f];
self.directionWebView.delegate = self;
NSString *urlMap = [NSString stringWithFormat:#"%#%f,%f&zoom=14", #"http://maps.google.com/maps?q=", self.coordLat, self.coordLong];
NSURL *url = [NSURL URLWithString:urlMap];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[self.directionWebView loadRequest:urlRequest];
}
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSLog(#"WebView start loading...");
self.progressView = [MRProgressOverlayView new];
self.progressView.mode = MRProgressOverlayViewModeIndeterminateSmall;
[self.view.window addSubview:self.progressView];
[self.progressView setTintColor:self.yellowColor];
[self.progressView setTitleLabelText:#"Loading ..."];
[self.progressView show:YES];
return YES;
}
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
[self.progressView dismiss:YES];
}
#end
Dont know why it is calling twice but you can do this.
if(!self.progressView){
self.progressView = [MRProgressOverlayView new];
self.progressView.mode = MRProgressOverlayViewModeIndeterminateSmall;
[self.view.window addSubview:self.progressView];
[self.progressView setTintColor:self.yellowColor];
[self.progressView setTitleLabelText:#"Loading ..."];
[self.progressView show:YES];
}
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
[self.progressView dismiss:YES];
self.progressView = nil;
}
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
it may be triggered more than once, e.g redirects, iframe loading and so on. It's very inconvenient to initialise objects here.
Use Lazy Initialization design pattern for it
- (MRProgressOverlayView *)progressView {
if (_progressView) {
_progressView = [... alloc] init];
// ... setup your progressView
}
return _progressView;
}
btw, you forgot about error handling:
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
// You need to stop loading indicator here, right?!
}
Second thing is - (maybe for you case it's not a big deal) but usually it's tricky to exactly determine when UIWebView stopped loading (all the resources loaded, AJAX requests and so on)
Personally I'm using something like code below to manage activity indicator start/stop behaviour for UIWebView
#pragma mark UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
NSLog(#"Webview (%p) starting to load URL: %#", self, request.URL);
self.URL = request.URL;
return YES;
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
[self.spinner startAnimating];
self.webViewLoadingCount++;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
self.webViewLoadingCount--;
if (self.webViewLoadingCount > 0) return;
[self.spinner stopAnimating];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
self.webViewLoadingCount--;
[self.spinner stopAnimating];
// Ignore NSURLErrorDomain error (-999).
if (error.code == NSURLErrorCancelled) return;
// Ignore "Frame Load Interrupted" errors
if (error.code == 102 && [error.domain isEqual:#"WebKitErrorDomain"]) return;
NSLog(#"WebView (%p) experienced an error: %#.", self, [error localizedDescription]);
}
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
This delegate method can be called multiple times (in case of redirection for example). So I would recommend to move your Progress view init code to viewDidLoad method.
- (void)viewDidLoad {
[super viewDidLoad];
//...
self.progressView = [MRProgressOverlayView new];
self.progressView.mode = MRProgressOverlayViewModeIndeterminateSmall;
[self.view.window addSubview:self.progressView];
[self.progressView setTintColor:self.yellowColor];
[self.progressView setTitleLabelText:#"Loading ..."];
}
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"WebView start loading...");
[self.progressView show:YES];
return YES;
}
-(void)webViewDidFinishLoad:(UIWebView *)webView {
[self.progressView dismiss:YES];
}
I can't load local epub file (from document directory) in wkwebview. It's working in simulator but not in device. I learned that it's a bug for iOS 8 from here. Is it already solved for iOS 8 ? Please help me what should i do. I got error in device as -
The operation couldn't be completed. (KCFErrorDomainCFNetwork error 1.)
Here is code snippet -
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.webView removeObserver:self forKeyPath:#"loading"];
[self.webView removeObserver:self forKeyPath:#"estimatedProgress"];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.webView addObserver:self forKeyPath:#"loading" options:NSKeyValueObservingOptionNew context:nil];
[self.webView addObserver:self forKeyPath:#"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
[self.progressView setProgress:0.0f animated:NO];
if ([self.documentDirectory checkEpubFileIfExistsAtPath:self.epubFolder]) {
NSString *filePath = [NSString stringWithFormat:#"%#/%#/%#/OEBPS/%#", [self.documentDirectory getDocumentsDirectory], self.epubFolder, self.epubName, [_html_link substringToIndex:[_html_link rangeOfString:#"#"].location]];
//Loading webview with progress bar action
if ([_html_link rangeOfString:#"#"].location != NSNotFound) {
self.tag = [_html_link substringFromIndex:[_html_link rangeOfString:#"#"].location];
NSURL *URL = [NSURL fileURLWithPath:filePath];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
[self.webView loadRequest:request];
}
} else {
NSDictionary *object = [self.alertMessages getMessageObj:#"translationNotAvailable"];
[self presentViewController:[self.alertController alertWithCustomOkayAction:[object objectForKey:#"title"] message:[object objectForKey:#"msg"] callback:^(void) {
[self dismissViewControllerAnimated:YES completion:nil];
}] animated:YES completion:nil];
}
}
//Constraints for Web View
- (void) setConstraintsForWebView {
[self.webView setTranslatesAutoresizingMaskIntoConstraints:NO];
WKWebView *webView = self.webView;
UIProgressView *progressView = self.progressView;
UIToolbar *toolBar = self.toolBar;
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-8-[webView]-8-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(webView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[progressView]-0-[webView]-[toolBar]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(progressView, webView, toolBar)]];
}
- (void)viewDidLoad {
[super viewDidLoad];
//Do any additional setup after loading the view.
self.alertController = [AlertController new];
self.alertMessages = [AlertMessages new];
self.documentDirectory = [DocumentDirectory new];
self.languageController = [LanguageController new];
//Set observer for webview load
self.webView = [[WKWebView alloc] initWithFrame:CGRectZero];
self.webView.navigationDelegate = self;
[self.view insertSubview:self.webView belowSubview:self.progressView];
[self setConstraintsForWebView];
}
#pragma mark KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:#"loading"]) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:self.webView.loading];
} else if ([keyPath isEqualToString:#"estimatedProgress"]) {
self.progressView.hidden = self.webView.estimatedProgress == 1;
self.progressView.progress = self.webView.estimatedProgress;
}
}
#pragma mark Web view navigation delegate
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
[self.progressView setProgress:0.0f animated:NO];
if (self.tag) {
[self.webView evaluateJavaScript:[NSString stringWithFormat:#"window.location.hash='%#'", self.tag] completionHandler:nil];
}
}
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
[self presentViewController:[self.alertController alertWithAction:#"Error!" message:error.localizedDescription] animated:YES completion:nil];
}
After more than 1 year I found the solution, we need to use loadFileURL to have access to the local resources, here is my working code with WKWebView, plus instead of load I use loadHTMLString. vistaweb in my WebView BTW
Thanks to this answer : Load local web files & resources in WKWebView
Sorry but is in Swift
do {
let local = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)[0]
// Loading: Library/Caches/repositorioLocal/esferas/znvUifZhH8mIDr09cX8j/index.html
let resourceFolder = "repositorioLocal/esferas/znvUifZhH8mIDr09cX8j"
let fileToLoad = "index.html"
let urlToFolder = URL(fileURLWithPath: local).appendingPathComponent(resourceFolder)
let urlToFile = URL(fileURLWithPath: local).appendingPathComponent(resourceFolder).appendingPathComponent(fileToLoad)
let fileContent = try String(contentsOf: urlToFile)
let webConfiguration = WKWebViewConfiguration()
webConfiguration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs")
webConfiguration.allowsInlineMediaPlayback = true
vistaweb = WKWebView(frame: self.view.frame, configuration: webConfiguration)
self.vistaweb.loadFileURL(urlToFolder, allowingReadAccessTo: urlToFolder)
self.vistaweb.loadHTMLString(fileContent, baseURL: urlToFile)
self.view.addSubview(vistaweb)
} catch let error {
print("Error: \(error.localizedDescription)")
}
I have uiwebview and i would like to prevent reload the current url when i change orientation from portrait to landscape and vice versa.
Do you have any idea?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
website.delegate = self;
[self home];
}
- (void)home {
// Create a URL object
NSURL *isuURL = [NSURL URLWithString: #"http://www.example.com"];
// URL Request Object
NSURLRequest *requestObject = [NSURLRequest requestWithURL:isuURL];
// Load the request in the UIWebView
[website loadRequest:requestObject];
}
I think it is help you:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation))
{
[website stopLoading];
} else if ([website isLoading])
{
[website reload]; // or [website loadRequest:requestObject];
}}
TRY This:
if(! [myWebView isLoading])
{
NSURL *isuURL = [NSURL URLWithString: #"http://www.example.com"];
// URL Request Object
NSURLRequest *requestObject = [NSURLRequest requestWithURL:isuURL];
// Load the request in the UIWebView
[website loadRequest:requestObject];
}
Thanks a lot guys for your help.
Here is the final solution to my problem
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
if ([website isLoading]) {
[website reload];
}
else {
[website stopLoading];
}
}
else if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
if ([website isLoading]) {
[website reload];
}
else {
[website stopLoading];
}
}
}