All,
I am displaying a URL in UIWebview and i have to perform some click actions and I am able to using click function in javascript (I am able to get callbacks to objective C code as well).
Now i want to migrate to WKWebview and i have below code written with delegate methods
WKPreferences *preferences = [[WKPreferences alloc] init];
preferences.javaScriptEnabled = YES;
WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init];
configuration.preferences = preferences;
self.webKitView = [[WKWebView alloc] initWithFrame: [[self view] bounds]configuration:configuration];
self.webKitView.navigationDelegate = self;
[self.webKitView loadHTMLString:htmlString1 baseURL:nil];
[self.view addSubview:self.webKitView];
Delegate method
(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
NSURLRequest *request = navigationAction.request;
decisionHandler(WKNavigationActionPolicyAllow);
}
Now i am able to display same as in Webview, I am performing Click actions but i am not able to call.
Can any one how can i proceed
Related
my system version is iOS 11.2.6 but i think in higher version have the same appearance.
i post a request in wkwebview like this and it works fine
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.url]];
request.HTTPMethod = #"POST";
request.HTTPBody = [postStr dataUsingEncoding:NSUTF8StringEncoding];
WKWebView *webView = [[WKWebView alloc]initWithFrame:rectDown];
webview.frame = self.view.frame;
[webview loadRequest:request];
[self.view addSubview:webview];
but if i implement the decidePolicyForNavigationAction delegate method like down,the nodejs server can't receive any post data
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:
(WKNavigationAction *)navigationAction decisionHandler:(void (^)
(WKNavigationActionPolicy))decisionHandler{
decisionHandler(WKNavigationActionPolicyAllow);
}
and I want to reuse a wkwebview object anyone have a good idea?
additional i found that when i first load the post request and back then reload and back again reload again it's always works right ,but if I reuse the wkwebview load any other url like google then it can't load the post request anymore.if if don't implement the delegate decidePolicyForNavigationAction method ,it will always works fine.
so ,this is a conflict between decidePolicyForNavigationAction and a reuse wkwebview?
I use this code to format the reuse wkwebview when the wkwebview's controller is remove
-(void)webFormat{
if (#available(iOS 9.0,*)) {
NSSet *websiteDataTypes = [NSSet setWithObjects:WKWebsiteDataTypeDiskCache,
WKWebsiteDataTypeOfflineWebApplicationCache,
WKWebsiteDataTypeMemoryCache,
nil];
// NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes];
NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
}];
}
[self.configuration.userContentController removeScriptMessageHandlerForName:kScriptHandlerName];
[self.configuration.userContentController removeAllUserScripts];
[self stopLoading];
[self loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"about:blank"]]];
self.scrollView.delegate = nil;
[self setUIDelegate:nil];
}
I fix this by add code
self.navigationDelegate = nil
in webFormat function .Even when the function webFormat run ,self.navigationDelegate is nil already;I thought that when the viewController remove,as the navigationDelegate of wkwebview ,left something in the corner and influence the webview's next load.who knows.
I'm testing the WKWebView with local file, which is working in the simulator but it is not working in the device
#interface EDPresentationViewController ()<WKNavigationDelegate,WKScriptMessageHandler>
#property(nonatomic,strong)WKWebView *webView;
#property(nonatomic,strong)EDPresentationController *presentationController;
#end
#implementation EDPresentationViewController
-(void)viewDidLoad
{
[super viewDidLoad];
self.presentationController = [[EDPresentationController alloc]init];
WKWebViewConfiguration *webConfiguration = [[WKWebViewConfiguration alloc]init];
self.webView = [[WKWebView alloc]initWithFrame:self.view.frame configuration:webConfiguration];
NSURL *presentationFolder = [self.presentationController url];
NSURLRequest *request = [NSURLRequest requestWithURL:presentationFolder];
[self.webView loadRequest:request];
}
I grant the url from:
NSURL *presentationFolder = [self.presentationController url];
is ok, because I tested the same code with a UIWebview and works!
I always get the same error:
Could not create a sandbox extension for '/'
This wasn't work, I guess it would work in Objective-C as in swift
iOS Webkit not working on device, but works on simulator at swift
Any idea will be appreciated, thanks
Update 2-12-2014
I've discovered this could be a bug in iOS 8.1 and it may be fixed in 8.2
https://devforums.apple.com/thread/247777?start=25&tstart=0
I've tested moving the files to the temporary folder and I didn't get any error but the webView is just empty.
I've tested the same code (temporary folder) with a UIWebView and works fine!
Also, I've tried this:
https://stackoverflow.com/a/26054170/426180
As I could find out, this works because the css and the javascript is embebed in the html.
Try XWebView which has a very tiny embedded http server. It's much smaller than the GCDWebServer. A loadFileURL:allowingReadAccessToURL method is added through extension, so you are not aware of the server.
This worked like a charm ...
#interface ViewController () <WKScriptMessageHandler, WKNavigationDelegate>
...
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKUserContentController *controller = [[WKUserContentController alloc] init];
configuration.userContentController = controller;
[configuration.preferences setValue:#"TRUE" forKey:#"allowFileAccessFromFileURLs"];
self.webView = [[WKWebView alloc] initWithFrame:[UIScreen mainScreen].bounds configuration:configuration];
self.webView.navigationDelegate = self;
// Also if you'd have bouncing problem
self.webView.scrollView.bounces = false;
self.webView.scrollView.alwaysBounceVertical = false;
[self.view addSubview:self.webView];
NSString* productURL = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"htmlapp/home.html"];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:productURL]];
[self.webView loadRequest:request];
I'm trying to load a web page in a WKWebView control without loading it as a subview:
WKPreferences *preferences = [[WKPreferences alloc] init];
preferences.javaScriptEnabled = YES;
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.preferences = preferences;
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
webView.navigationDelegate = self;
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setValue:#"Safari" forHTTPHeaderField:#"User-agent"];
[webView loadRequest:urlRequest];
The url I'm trying to load is this:
https://www.google.com/search?q=mustang
The following WKNavigationDelegate method is not being called:
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
[webView evaluateJavaScript:#"document.getElementsByTagName('html')[0].outerHTML" completionHandler:^(id result, NSError *error) {
NSLog(#"Result %#", result);
}];
}
My NSObject class conforms to the WKNavigationDelegate protocol.
Do I need to do something else?
Greatly appreciate any help.
I had a WK Scheme Handler in my code and I used it for tracking requests done and completed (amongst other things).
It showed that if one resource load failed, the didFinishNavigation: did not get called.
So, your content needs to load in its entirety for this to ever be called.
Loading the same URL seems to work for me.
Do note:
The didFinishNavigation method is called after main frame load completes (this includes loading stuff from other hosts which are present in the main frame). So if something would be responding slow the didFinishNavigation method won't be invoked until resolved.
I want to make phone call using UIWebView. I tried below code which works fine in if I simply put a button and on button click execute below code. But currently on button click, I call an api and on response I execute below code.
// Make a call to given phone number
- (void)callPhoneNumber:(NSString *)phoneNumber
{
if (!self.webView)
{
webView = [[UIWebView alloc] init];
[self.view addSubview:self.webView];
self.webView.delegate = self;
}
// Remove non-digits from phone number
phoneNumber = [[phoneNumber componentsSeparatedByCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]] componentsJoinedByString:#""];
// Make a call
NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:#"tel:%#", phoneNumber]];
[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
}
Its not even calling webview delegate methods.
What can be the reason?
Please note that I want to call using webview only, so please don't suggest to use native contact app. Using webview keeps flow within the app. When call is ended users is in app only. Using native app, if user wants to come back to my app user has to manually open the app.
To dial a phone number you have to call -[UIApplication openURL:]:
NSString *phoneNumber = #"+5512345678";
NSURL *phoneNumberURL = [NSURL URLWithString:[NSString stringWithFormat:#"tel://%#", phoneNumber]];
[[UIApplication sharedApplication] openURL:phoneNumberURL];
Why not use this?
NSString *phoneNumberURL = [#"telprompt://" stringByAppendingString: phoneNumber];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:phoneNumberURL]];
This takes the user back to the app automatically once the call is finished. I hope that is what you want to achieve using webview.
https://stackoverflow.com/a/12065542/569497
Are you sure self.webView has been initialized?
Change: webView = [[UIWebView alloc] init];
To: self.webView = [[UIWebView alloc] init];
and this: [NSString stringWithFormat:#"tel:phoneNumber"] don't work; try: [NSString stringWithFormat:#"tel:%#",phoneNumber]
Personally, however, I never tried to make a phone call in this way.
If you want to call via UIWebView then use this example:
+ (void)callWithString:(NSString *)phoneString
{
[self callWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"tel:%#",phoneString]]];
}
+ (void)callWithURL:(NSURL *)url
{
static UIWebView *webView = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
webView = [UIWebView new];
});
[webView loadRequest:[NSURLRequest requestWithURL:url]];
}
I read somewhere to read javascript console messages using the
- (void)webView:(WebView *)webView addMessageToConsole:(NSDictionary *)message
delegate method from the UIDelegate. But how/where do I need to set the delegate of the WebView (not the UIWebView) to my custom delegate?
I know Apple doesn't allow this in the AppStore, but I just want to implement this for debugging purposes.
What I tried so far:
- (void)webView:(id)sender didClearWindowObject:(id)windowObject forFrame:(WebFrame*)frame
{
[webView setUIDelegate:[[MyCustomUIDelegate alloc] init]];
}
and
-(void) webView:(id)webView windowScriptObjectAvailable:(id)newWindowScriptObject
{
[webView setUIDelegate:[[MyCustomUIDelegate alloc] init]];
}
This post may help you:
How can my iPhone Objective-C code get notified of Javascript errors in a UIWebView?
You can hook UIWebView control to hidden WebKit framework and get all exceptions, executed functions and similar.
Another way is posted here: Inject javascript code into the response that invoke to a objecie-c function.
NSString* path = [[NSBundle mainBundle] pathForResource:#"script"
ofType:#"js"];
NSString* content = [NSString stringWithContentsOfFile:path
encoding:NSUTF8StringEncoding
error:NULL];
[sender stringByEvaluatingJavaScriptFromString:content];
for exapmle the javascript code may be like:
console = new Object();
console.log = function(log) {
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", "ios-log:#iOS#" + log);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
console.debug = console.log;
console.info = console.log;
console.warn = console.log;
console.error = console.log;
and the objective-c code like:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *requestString = [[[request URL] absoluteString] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
//NSLog(requestString);
NSLog(#"Request: %#", requestString);
if ([requestString hasPrefix:#"ios-log:"]) {
NSString* logString = [[requestString componentsSeparatedByString:#":#iOS#"] objectAtIndex:1];
NSLog(#"UIWebView console: %#", logString);
return NO;
}
return YES;
}