Loading local file in WKWebView doesn't working in device - ios

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)")
}

Related

Why doesn't observeValueForKeyPath trigger in my webView?

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.
}

How to load cordova webview in my viewcontroller?

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!

How to enable modaldialog in Cocoa WebView

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];
}

show progress bar until video loads IOS7

Hi in my application I'm playing the video using URL. I'm passing the video URL form my server now the problem its taking to much time to play the video. So i want to show progress bar until its load the video .
So i have used the MBProgressHUD for progress bar its showing the progress bar but the video is not playing please tell where I'm doing wrong.
My code.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString * currentVideo = [videoarray1 objectAtIndex:indexPath.row];
NSString *strurl=[self urlencode:currentVideo];
NSURL *url=[NSURL URLWithString:strurl];
NSURLRequest *req=[NSURLRequest requestWithURL:url];
NSURLConnection *con=[NSURLConnection connectionWithRequest:req delegate:self];
if (con) {
datas=[[NSMutableData alloc]init];
}
spinner = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
spinner.mode = MBProgressHUDModeCustomView;
[spinner setLabelText:#"Loading file....."];
[spinner setLabelFont:[UIFont systemFontOfSize:15]];
[spinner show:YES];
}
-(NSString *)urlencode:(NSString *)str
{
NSString *encodeString=(NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)str, NULL, (CFStringRef)#"", kCFStringEncodingUTF8));
return encodeString;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSLog(#"%lld",[response expectedContentLength]);
self.length = [response expectedContentLength];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data1{
[datas appendData:data1];
float progress = (float)[datas length]/(float)self.length;
NSLog(#"%f",progress);
float check=progress*100;
if (check==100) {
[spinner hide:YES];
[spinner removeFromSuperViewOnHide];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSData *data = datas;
NSLog(#"%#",data);
NSString* myurl;
myurl = [[NSString alloc] initWithData:datas encoding:NSASCIIStringEncoding];
NSLog(#"%#",myurl);
_movieplayer = [[MPMoviePlayerController alloc]initWithContentURL: [NSURL URLWithString:myurl]];
[[_movieplayer view] setFrame: CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
[self.view addSubview: [_movieplayer view]];
[_movieplayer setShouldAutoplay:YES];
[_movieplayer prepareToPlay];
[_movieplayer play];
}
I have used the above code its not playing the video please tell where I'm doing wrong in the above code how to achieve this one.
Thanks.
1.create new view control
2.pass your videoarray1 value to nextvieww control i mean your video url
3.add following code nextview control
- (void)viewDidLoad
{
[super viewDidLoad];
self.indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.indicator.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
self.indicator.center = self.view.center;
[self.view addSubview:self.indicator];
[self.indicator startAnimating];
_movieplayer = [[MPMoviePlayerController alloc]initWithContentURL: [NSURL URLWithString:[self urlencode:self.strPlayUrl]]];
[[_movieplayer view] setFrame: CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
[self.view addSubview: [_movieplayer view]];
[_movieplayer setShouldAutoplay:YES];
[_movieplayer prepareToPlay];
//this is the line we need to do
[self.view insertSubview:self.movieplayer.view belowSubview:self.indicator];
[self.movieplayer play];
}
- (void)viewDidAppear:(BOOL)animated {
NSLog(#"VIEW DID LOAD");
// Register to receive a notification that the movie is now in memory and ready to play
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieLoadStateDidChange:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:nil];
}
-(void)movieLoadStateDidChange:(id)sender
{
NSLog(#"STATE CHANGED");
if(MPMovieLoadStatePlaythroughOK ) {
NSLog(#"State is Playable OK");
NSLog(#"Enough data has been buffered for playback to continue uninterrupted..");
self.indicator.hidden = YES;
[ self.indicator stopAnimating];
}
}
-(NSString *)urlencode:(NSString *)str
{
NSString *encodeString=(NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)str, NULL, (CFStringRef)#"", kCFStringEncodingUTF8));
return encodeString;
}

Making an iphone webview go to a different webaddress when only the prefix is in the address bar

im curently working on a school project and my iphone app has been rejected twice and I know why. the solution to my problem though is tough. here i have the .m file from my project and I have a web based app. right now, if there is only http:// in the address bar, it displays an error that says the url's host is not found because it is only http:// and my app was rejected for that. what I want it to do is when only http:// is in the address bar, to make it go to a different web site. PLEASE HELP!! Plus I'm on iOS 6
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
-(void)bannerViewDidLoadAd:(ADBannerView *)banner{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[banner setAlpha:1];
[UIView commitAnimations];
}
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[banner setAlpha:0];
[UIView commitAnimations];
}
-(IBAction)press {
label.hidden = 0;
addressBar.hidden = 0;
browserPlace.hidden = 1;
button.hidden = 1;
button2.hidden = 0;
}
-(IBAction)press2
{
label.hidden = 1;
addressBar.hidden = 1;
browserPlace.hidden = 0;
button.hidden = 0;
button2.hidden = 1;
}
- (void)viewDidLoad
{
label.hidden = 1;
addressBar.hidden = 1;
browserPlace.hidden = 0;
button.hidden = 0;
button2.hidden = 1;
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
addressBar.text = [defaults objectForKey:#"history"];
[self searchBarSearchButtonClicked:addressBar];
}
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
[browserPlace loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[self parseUrl:addressBar.text]]]];
}
-(NSString*) parseUrl: (NSString*) url
{
if ([url hasPrefix:#"http://"] || [url hasPrefix:#"https://"])
return url;
else
return [NSString stringWithFormat:#"http://%#", url];
}
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return YES;
}
-(void)webViewDidStartLoad:(UIWebView *)webView
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:addressBar.text forKey:#"history"];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
label2.hidden = 0;
}
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
label2.hidden = 1;
}
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
NSLog(#"%#", [error description]);
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
label2.hidden = 1;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"ERROR" message:[error description] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
[searchBar setShowsCancelButton:YES animated:YES];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:YES];
}
-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
[searchBar setShowsCancelButton:NO animated:YES];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault animated:YES];
}
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Update your parseUrl: method. Check to see if the URL is just "http://":
- (NSString *)parseUrl:(NSString *)url {
if (url.length == 0 || [url isEqualToString:#"http://"]) {
return #"http://www.someplacecool.com"; // put your desired URL here
} else if ([url hasPrefix:#"http://"] || [url hasPrefix:#"https://"]) {
return url;
} else {
return [NSString stringWithFormat:#"http://%#", url];
}
}
You should also add other error checking in case the user enters any other invalid URLs.
I think you can make use of
(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
You can check the [request URL] and also its scheme.
Try to redirect the URL to different one in this method and return the respective BOOL value (YES/NO).

Resources