Share WKWebView Cookies With UIWebView - ios

I'm trying to share WKWebView Cookies with UIWebView for getting all cookies. I know its very simple to get all cookies from UIWebView as compare WKWebView.
I create two WebView's (WKWebView, UIWebView) in Tabbed Application Template. Below method that i am using for share WKWebView cookies with UIWebView but didn't get success.
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: #escaping (WKNavigationResponsePolicy) -> Void) {
let response = navigationResponse.response as? HTTPURLResponse
let cookies = HTTPCookie.cookies(withResponseHeaderFields: response?.allHeaderFields as! [String : String], for: (response?.url)!)
HTTPCookieStorage.shared.cookieAcceptPolicy = HTTPCookie.AcceptPolicy.always
for cookie in cookies {
HTTPCookieStorage.shared.setCookie(cookie)
}
decisionHandler(WKNavigationResponsePolicy.allow);
}
Using above code when i Login Into my account from WKWebView, UiWebView didn't Login me already.
I also tried to share UIWebView Cookies With WKWebView, and it worked.
Please can anyone tell me how i can share WKWebView Cookies With UIWebView or how i can get all cookies from WKWebView?
Thanks

You need to set the wkwebview cookies by following the steps below
first in the initialization is to execute the script to set up Cookies:
-(void)initWebView
{
WKWebViewConfiguration *webViewconfiguration = [[WKWebViewConfiguration alloc] init];
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
if(URL.host hasSuffix:baseDomain){
//Here to determine whether the domain name is their own website
NSString *jScript = [self setCookies];
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[wkUController addUserScript:wkUScript];
}
webViewconfiguration.userContentController = wkUController;
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, width, height) configuration:webViewconfiguration];
}
//The script that executes may be slightly different
+(NSString *)setCookies
{
NSString *script = [NSString string];
for (NSHTTPCookie *httpCookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies])
{
NSString *cookie = [NSString stringWithFormat:#"%#=%#;domain=%#;path=%#",httpCookie.name,httpCookie.value,httpCookie.domain,httpCookie.path?:#"/"];
script = [script stringByAppendingString:[NSString stringWithFormat:#"document.cookie='%#';",cookie]];
}
return script;
}
And then manually add cookies to the header of the HTTP when creating the NSURLRequest object:
- (void)loadRequest:(NSURLRequest *)request
{
//Here to determine whether the domain name is their own website
if ([request.URL.host hasSuffix:baseDomain]){
NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:request.URL];
NSString *cookies = #""; //setting Cookies
[mutableRequest addValue:cookies forHTTPHeaderField:#"Cookie"];
}
// do request
}

This is really painful to setup cookies and load webview, it's tricky to set cookies before loading webview. if you set cookies in just a delegate method it never load page first time. you must take care of cookies are done before loading page. you can ceck my answer in other question, but it is in swift but you can follow the same technique in objective c. Can I set the cookies to be used by a WKWebView?

Related

How are cookies managed in UIWebView and WKWebView?

I am migrating from UIWebView to WKWebView and facing problem in cookies management. As app need to support iOS 10 I am not adding cookies through WKHTTPCookieStore instead, I am following the below code:
- (void)loadURL:(NSString *)url
{
NSMutableURLRequest * req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray* cookies = [storage cookiesForURL:[NSURL URLWithString:url]];
NSMutableString *cookieStr = [NSMutableString string];
for (NSHTTPCookie *cookie in cookies) {
if (cookieStr.length) {
[cookieStr appendString:#"; "];
}
[cookieStr appendFormat:#"%#=%#", cookie.name, cookie.value];
}
NSLog(#"Cookie: %#",cookieStr);
[req addValue:cookieStr forHTTPHeaderField:#"Cookie"];
NSMutableString *cookieStrAfterDocLoad = [NSMutableString string];
for (NSHTTPCookie *cookie in cookies) {
[cookieStrAfterDocLoad appendFormat:#"document.cookie = '%#=%#';", cookie.name, cookie.value];
}
WKUserScript *userScript = [[WKUserScript alloc] initWithSource: cookieStrAfterDocLoad
injectionTime: WKUserScriptInjectionTimeAtDocumentStart
forMainFrameOnly:NO];
[self.wkWebView.configuration.userContentController addUserScript:userScript];
[self.wkWebView loadRequest:req];
}
I need to add the cookies after the document load to maintain the session for internal navigation.
This is not the correct way as the new cookies may be added or old may be modified at the time of page load. This needs to be done in many other controllers.
My question is how can I know if the cookies were added at every for loadRequst in UIWebview, or is there any other correct way to handle this situation in WKWebview as some webpage load might not need the cookies?
Is this the correct way to add cookies for every loadRequest?

When I implement the decidePolicyForNavigationAction delegate methond,the Post request will be invalid in WKWebView

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.

Changing link in UiWebView

I have to write very simple application whoes open link in UiWebView but I have a little problem because I want that UiWebView download link from outside data e.g. http://www.example.com/link.txt and check link on every run of application. I tried to download data to NSStringbut I don't have any ideas how to use this with UiWebView. Thanks for help!
Create an NSURLRequest with the URL you downloaded. Then you can change the WebView's content with loadRequest(_ request: NSURLRequest)
Swift 2.2:
let myURLString = "the url you read from the file"
let url = NSURL(string: myURLString)
let request = NSURLRequest(url)
//assuming, the property webView is the UIWebView you want to change
webView.loadRequest(request)
Objective-C:
NSString * myURLString = #"the url you read from the file";
NSURL * url = [[NSURL alloc] initWithString:myURLString];
NSURLRequest * request = [[NSURLRequest alloc] initWithURL:url];
//assuming, the property webView ist the UIWebView you want to change
[self.webView loadRequest:request];
More information:
UIWebView
NSURLRequest
NSURL

didFinishNavigation not being called

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.

Not able to make phone call using UIWebView

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

Resources