WKWebView evaluate JavaScript return value
Update: This is not working on iOS 12+ anymore.
I solved this problem by waiting for result until result value is returned.
I used NSRunLoop for waiting, but I'm not sure it's best way or not...
Here is the category extension source code that I'm using now:
@interface WKWebView(SynchronousEvaluateJavaScript)
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
@end
@implementation WKWebView(SynchronousEvaluateJavaScript)
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
{
__block NSString *resultString = nil;
__block BOOL finished = NO;
[self evaluateJavaScript:script completionHandler:^(id result, NSError *error) {
if (error == nil) {
if (result != nil) {
resultString = [NSString stringWithFormat:@"%@", result];
}
} else {
NSLog(@"evaluateJavaScript error : %@", error.localizedDescription);
}
finished = YES;
}];
while (!finished)
{
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
return resultString;
}
@end
Example code:
NSString *userAgent = [_webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
NSLog(@"userAgent: %@", userAgent);
How do I get WKWebView.evaluateJavaScript to return data in a function call
you should use a completion handler, something like this:
func checkTitle (forWebView webView: WKWebView, title: String, completion: @escaping (_ titleString: String?) -> Void) {
webView.evaluateJavaScript("document.title", completionHandler: { (innerHTML, error ) in
// Logic here
completion(innerHTML as? String)
})
}
WKWebView - evaluate JavaScript without seeing changes
This looks like Apple's defect, because updateUIView is called, but evaluateJavaScript
(internal JavaScript) generates exception, because bridge.onMessage is lost and not a function more.
Here is found work-around - reset WebView on scene activation (app comes into foreground), as it recreated with current states the previous values are preserved. Tested with Xcode 13.2 / iOS 15.2
struct DemoView: View {
@Environment(\.scenePhase) var scenePhase
@State private var headline: String = "Initial"
@State private var reset = false
var body: some View {
NavigationView {
VStack {
Form {
TextField("Your headline", text: $headline)
}
WebView(headline: $headline).id(reset) // << here !!
.onChange(of: scenePhase) {
if case .active = $0 {
self.reset.toggle() // << here !!
}
}
}
}
}
}
WKWebView Evaluate Javascript without reloading page
[webView evaluateJavaScript:javascriptString completionHandler:nil];
performs the same function as the one you have listed for UIWebView
Related Topics
Custom CSS Properties, Why Not
Adding Style Stored in a Variable Inside React Class
Android Webview, Loading JavaScript File in Assets Folder
How to Detect When a CSS File Has Been Fully Loaded
Change the Fixed Navbar's Classes Depending on the Background of the Page Section It Hovers
Performance Difference Between JavaScript Created Inline Styles and JavaScript Created Stylesheets
Can't Change Bootstrap Tooltip Title
JavaScript Invalidcharactererror When Modifying a CSS Name with a Space
Divs Fixed and Unfixed Toggle Between Two Absolute Divs
Semantic-Ui Modal Size Keeps Extending to the Height of a Page
Jquery .Css() Function with Variables and Multiple Values
How to Extract R, G, B, a Values from CSS Color
Svg Foreignobject Not Working Properly on Safari
Swap Style Sheet with Localstorage
Jquery UI Datepicker: Don't Highlight Today When It Is Also Selected