Since webviewdidfinishload has been deprecated and the webKit delegates don't seem to trigger when navigating to another url (from what I can see), I looked into using observer forKeyPath, like here:
How can I detect when url of amp page changed with WKWebview
And while this seems like a valid approach, I can't get the observeValue to trigger. At times it works, but most often it doesn't, and there doesn't seem to be any consistency.
- (void)setUpWebView {
NSString * urlString = [NSString stringWithFormat:#"www.thisisnottherealurl.com"];
NSURL *url = [NSURL URLWithString: urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
WKWebViewConfiguration *webViewConfig = [WKWebViewConfiguration new];
_webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:webViewConfig];
_webView.navigationDelegate = self;
_webView.translatesAutoresizingMaskIntoConstraints = NO;
_webView.alpha = 0.0f;
// _webView.alpha = 1;
[_webViewContainer addSubview:_webView];
[self startLoadingAnimation];
[_webView.topAnchor constraintEqualToAnchor:_webViewContainer.topAnchor].active = YES;
[_webView.bottomAnchor constraintEqualToAnchor:_webViewContainer.bottomAnchor].active = YES;
[_webView.rightAnchor constraintEqualToAnchor:_webViewContainer.rightAnchor].active = YES;
[_webView.leftAnchor constraintEqualToAnchor:_webViewContainer.leftAnchor].active = YES;
[_webView.heightAnchor constraintEqualToAnchor:_webViewContainer.heightAnchor].active = YES;
[_webView loadRequest:request];
//IMPORTANT PART
[_webView addObserver:self forKeyPath:#"url" options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld | NSKeyValueObservingOptionPrior context:nil];
}
And then the observeValue part:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
NSLog(#"🤩OBSERVED");
}
Now, this doesn't trigger. Instead of observing _webView I have also tried _webView.URL.absoluteString. But still, it doesn't trigger. I have added alternative options like so: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld | NSKeyValueObservingOptionPrior but still nothing.
What am I doing wrong?
Is there a better approach to this? Is there a delegate that actually trigger when navigating to another url link?
You can use this method from WKNavigationDelegate of WKWebView.
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSURLRequest* request = navigationAction.request;
if ([request.URL.urlString hasPrefix:#<Do ur checking here>])
{
decisionHandler(WKNavigationActionPolicyCancel); // Cancel the request
}
else
{
decisionHandler(WKNavigationActionPolicyAllow); // Allow the request.
}
Related
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!
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 know that this has been brought up many a times and answered twice as many on this site, however I think I may have something a little different and need to know if it is possible.
I am trying to load a banner ad from a website into a UIWebView in the app. All of this works flawlessly. However no matter what code I have tried to implement I cannot get it so that when the ad is clicked in the app it will launch in safari.
Basically I am wanting to have my own Ad server. The ad is managed ad hosted on our site. The banner has the link embedded into it by the server.
Here is the code I am using.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *string;
string = #"http://www.samplesite.com/mobile_ads";
NSURL *url = [NSURL URLWithString: string];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[self.adBox loadRequest:requestObj];
}
-(BOOL) adBox:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ( inType == UIWebViewNavigationTypeLinkClicked ) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
}
Any ideas of where I should go?
In your UIWebViewDelegate's webView:shouldStartLoadWithRequest:navigationType: method, do something like the following (assuming your ads have part of their URL identifiable):
- (void)methodThatCreatesTheWebview {
UIWebView *webview = [[UIWebView alloc] init];
webview.delegate = self;
}
// Portion of the URL that is only present on ads and not other URLs.
static NSString * const kAd = #"adSubdominOrSubDirectory";
// pragma mark - UIWebViewDelegate Methods
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
if ([request.URL.absoluteString rangeOfString:kAd] != NSNotFound) {
// Launch Safari to open ads
return [[UIApplication sharedApplication] openURL:request.URL];
} else {
// URL isn't an ad, so just load it in the webview.
return YES;
}
}
I have an .mp4 video(url) which was protected by Windows authentication. I would like to play using MPMoviePlayerController.
I've implemented some code, and I'm sure I'm close!
So, I'm trying to "unlock" the mp4 url using NSURLConnection. It works, but when I try to access the same url with initWithContentURL, it doesn't work. (it cannot "see" that I've entered the info previously.
So, the question was; how do I onlock a folder/url permanently, OR how can I provide MPMoviePlayerController a NSURLConnection instead of NSURL.
1- So, here's the steps I've taken:
- (void)viewDidLoad{
[super viewDidLoad];
//[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"]]];
[self tryConnection];
}
2--> I'm trying to access the protected URL(this was working)
- (void) tryConnection{
NSURLRequest* request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://www.abcd.com/_develop/video/01.mp4"]];
NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
//[request release];
//[connection release];
}
3- this was called properly
- (BOOL)connection:(NSURLConnection*)conn canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace*)protectionSpace {
if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodNTLM])
return YES;
// Explicitly reject ServerTrust. This is occasionally sent by IIS.
if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust])
return NO;
return NO;
}
4- this was called properly
- (void)connection:(NSURLConnection*)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge*)challenge{
NSLog(#"didReceiveAuthenticationChallenge");
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodNTLM])
[[challenge sender] useCredential:[NSURLCredential
credentialWithUser:#"1234"
password:#"5678"
persistence:NSURLCredentialPersistenceNone] forAuthenticationChallenge:challenge];
}
4- this was called properly. From here, that's great because i know that the url was Unlock. So... how to play it with MPMoviePlayer?
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;{
NSLog(#"received response via nsurlconnection");
[self moviePlayerGO];
}
4- Stay black... :(
-(void)moviePlayerGO{
NSURL *movieURL = [NSURL URLWithString:#"http://www.abcd.com/_develop/video/01.mp4"];
//NSURL *movieURL = [NSURL URLWithString:#"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
moviePlayer.shouldAutoplay = YES;
[[moviePlayer view] setFrame: CGRectMake(0.0, 0.0, 350.0, 250.0)]; // 2X the native resolution
[self.view addSubview: [moviePlayer view]];
}
I have an app with a UIWebView inside a UIViewController. I load HTML from a web service as a string like this:
self.webView loadHTMLString:_string baseURL:nil
Is it possible for the HTML links in this string to be opened in the browser and not in the UIWebView in my app? How can I do this?
I have tried this in the UIViewController that "hosts" the UIWebVIew:
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
[[UIApplication sharedApplication] openURL:[request URL]];
return NO;
}
return YES;
}
It doesn't seem to be working....
Any ideas?
Have you set the delegate of the UIWebView to your UIViewController? There's nothing obviously wrong with your code as far as I can see, so it's likely to be something small like that.
Add this in class..
#interface yourViewController : UIViewController
<UIWebViewDelegate>
Add this in View did load
- (void)viewDidLoad
{
[description loadHTMLString:string baseURL:nil];
description.delegate = self;
}
Add this in your .m file
-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ( inType == UIWebViewNavigationTypeLinkClicked ) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
return YES;
}
Note:
UIWebView *description;
#synthesize description;
Then It will work perfectly the way you deserve..!! :)
Set the delegate of the UIWebView to your UIViewController after that use this UIWebview method and check the condition, for example now webview current url is google.com, if suppose you clicked on gmail the url contains the string with gmail. Use the below method it opened a safari browser and automatically loaded that url.
-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ( inType == UIWebViewNavigationTypeLinkClicked ) {
NSURL *url = [inRequest URL];
if ([[url absoluteString] rangeOfString:#"gmail"].location == NSNotFound) {
[[UIApplication sharedApplication] openURL:[inRequest URL]];
return NO;
}
}
return YES;
}
If you already setup properly the UIWebViewDelegate, simply doing
self.webView loadHTMLString:_string baseURL:nil
self.webView.delegate = self;
should work
Add this line (
self.webview.delegate = self;
)
For Example in viewController.m
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"];
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[self.webview loadHTMLString:htmlString baseURL:nil];
self.webview.delegate = self;
Apple introduced a Safari View Controller on iOS 9. Safari View Controller brings all of the features user expect from Safari over to your app without ever leaving it.
First we need to import Safari Services
#import <SafariServices/SafariServices.h>
For Objective C:-
NSString *yourUrl = #"http://yourURL";
SFSafariViewController *svc= [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString: yourUrl]];
[self presentViewController:svc animated:YES completion:nil];
For Swift:-
let svc = SFSafariViewController(URL: NSURL(string: self.urlString)!)
self.presentViewController(svc, animated: true, completion: nil)
Yes, in your hyperlink tag add
target="blank"
And one question mark will be fine, thank you