Getting invokeUndefinedMethodFromWebScript to work in Swift
I am trying to get Javascript-Swift interface work with WKWebView and someone seems to have got it working here.
However I am unable to get it working in Swift (I am new to Swift and newer to Obj-C). I tried following code in ViewController.swift with WKWebView added to Main.storyboard and connected:
import WebKit
class ViewController: NSViewController, WKUIDelegate {
@IBOutlet weak var wkWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "http://127.0.0.1:8080")
let request = URLRequest(url: url!)
wkWebView!.configuration.preferences.javaScriptEnabled = true
wkWebView!.load(request)
}
}
extension WKWebView {
open override func invokeUndefinedMethod(fromWebScript name: String!, withArguments arguments: [Any]!) -> Any! {
return "Hello From Swift"
}
}
and on HTML side:
<html>
<body>
<p>Hello World</p>
<input type=text id='i'/>
<input type=button value='Submit' onclick='document.getElementById("i").value = window.external.MY_ObjectiveCFunction();'>
</body>
</html>
But when I click on Submit button nothing happens. If I use document.getElementById("i") = "hello", it works though. @ctrlspace seems to have got it working somehow (See link above).
Any ideas?
ios swift xcode macos wkwebview
add a comment |
I am trying to get Javascript-Swift interface work with WKWebView and someone seems to have got it working here.
However I am unable to get it working in Swift (I am new to Swift and newer to Obj-C). I tried following code in ViewController.swift with WKWebView added to Main.storyboard and connected:
import WebKit
class ViewController: NSViewController, WKUIDelegate {
@IBOutlet weak var wkWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "http://127.0.0.1:8080")
let request = URLRequest(url: url!)
wkWebView!.configuration.preferences.javaScriptEnabled = true
wkWebView!.load(request)
}
}
extension WKWebView {
open override func invokeUndefinedMethod(fromWebScript name: String!, withArguments arguments: [Any]!) -> Any! {
return "Hello From Swift"
}
}
and on HTML side:
<html>
<body>
<p>Hello World</p>
<input type=text id='i'/>
<input type=button value='Submit' onclick='document.getElementById("i").value = window.external.MY_ObjectiveCFunction();'>
</body>
</html>
But when I click on Submit button nothing happens. If I use document.getElementById("i") = "hello", it works though. @ctrlspace seems to have got it working somehow (See link above).
Any ideas?
ios swift xcode macos wkwebview
add a comment |
I am trying to get Javascript-Swift interface work with WKWebView and someone seems to have got it working here.
However I am unable to get it working in Swift (I am new to Swift and newer to Obj-C). I tried following code in ViewController.swift with WKWebView added to Main.storyboard and connected:
import WebKit
class ViewController: NSViewController, WKUIDelegate {
@IBOutlet weak var wkWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "http://127.0.0.1:8080")
let request = URLRequest(url: url!)
wkWebView!.configuration.preferences.javaScriptEnabled = true
wkWebView!.load(request)
}
}
extension WKWebView {
open override func invokeUndefinedMethod(fromWebScript name: String!, withArguments arguments: [Any]!) -> Any! {
return "Hello From Swift"
}
}
and on HTML side:
<html>
<body>
<p>Hello World</p>
<input type=text id='i'/>
<input type=button value='Submit' onclick='document.getElementById("i").value = window.external.MY_ObjectiveCFunction();'>
</body>
</html>
But when I click on Submit button nothing happens. If I use document.getElementById("i") = "hello", it works though. @ctrlspace seems to have got it working somehow (See link above).
Any ideas?
ios swift xcode macos wkwebview
I am trying to get Javascript-Swift interface work with WKWebView and someone seems to have got it working here.
However I am unable to get it working in Swift (I am new to Swift and newer to Obj-C). I tried following code in ViewController.swift with WKWebView added to Main.storyboard and connected:
import WebKit
class ViewController: NSViewController, WKUIDelegate {
@IBOutlet weak var wkWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "http://127.0.0.1:8080")
let request = URLRequest(url: url!)
wkWebView!.configuration.preferences.javaScriptEnabled = true
wkWebView!.load(request)
}
}
extension WKWebView {
open override func invokeUndefinedMethod(fromWebScript name: String!, withArguments arguments: [Any]!) -> Any! {
return "Hello From Swift"
}
}
and on HTML side:
<html>
<body>
<p>Hello World</p>
<input type=text id='i'/>
<input type=button value='Submit' onclick='document.getElementById("i").value = window.external.MY_ObjectiveCFunction();'>
</body>
</html>
But when I click on Submit button nothing happens. If I use document.getElementById("i") = "hello", it works though. @ctrlspace seems to have got it working somehow (See link above).
Any ideas?
ios swift xcode macos wkwebview
ios swift xcode macos wkwebview
edited Jan 19 at 6:21
arun siara.cc
asked Jan 19 at 6:10
arun siara.ccarun siara.cc
11911
11911
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
You have found an old article which was written for an ancient WebView of macOS, not for WKWebView.
You use WKScriptMessageHandler to make interaction between JavaScript and Swift, when using WKWebView.
ViewController.swift:
import WebKit
class ViewController: NSViewController, WKUIDelegate {
@IBOutlet weak var wkWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "index", withExtension: "html")! //Simplified for testing
let request = URLRequest(url: url)
wkWebView.configuration.preferences.javaScriptEnabled = true
wkWebView.configuration.userContentController.add(self, name: "mySwiftMessage") //<-
wkWebView.load(request)
}
//...
}
extension ViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
switch message.name {
case "mySwiftMessage":
if let callbackName = message.body as? String {
message.webView?.evaluateJavaScript("(callbackName)('Hello From Swift');", completionHandler: nil)
}
default:
break
}
}
}
index.html:
<html>
<body>
<script>
function myCallback(value) {
document.getElementById("i").value = value;
}
</script>
<p>Hello World</p>
<input type=text id='i'/>
<input type=button value='Submit' onclick='window.webkit.messageHandlers.mySwiftMessage.postMessage("myCallback");'>
</body>
</html>
ADDITION
To make WKWebView work on prior iOS's than 11, you just need to instantiate it programmatically:
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var wkWebView: WKWebView! //<- NOT an IBOutlet
override func viewDidLoad() {
super.viewDidLoad()
let webConfig = WKWebViewConfiguration()
webConfig.preferences.javaScriptEnabled = true
webConfig.userContentController.add(self, name: "mySwiftMessage")
wkWebView = WKWebView(frame: self.view.bounds, configuration: webConfig)
view.addSubview(wkWebView)
//You may need to add some constraints...
//And create a better `index.html` for iOS...
let url = Bundle.main.url(forResource: "index", withExtension: "html")!
let request = URLRequest(url: url)
wkWebView.load(request)
}
//...
}
Thank you for the completely working solution.. I would also like to make it work for UIWebView to support iOS 9.0+ since WKWebView is only for iOS11+. Is it possible?
– arun siara.cc
Jan 19 at 8:34
I could not find such an elegant solution for UIWebView. Seems only workarounds are available (such as loading a custom url)
– arun siara.cc
Jan 19 at 8:40
1
You are mistaking the availability ofWKWebView, which is available since iOS 8. Just that you cannot use storyboard forWKWebViewbefore iOS 11. You just need to instantiate yourWKWebViewprogrammatically.
– OOPer
Jan 19 at 10:12
Excellent.. That worked too.. I wish I can upvote you more than once.. Thanks a ton!!
– arun siara.cc
Jan 19 at 10:23
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54264550%2fgetting-invokeundefinedmethodfromwebscript-to-work-in-swift%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You have found an old article which was written for an ancient WebView of macOS, not for WKWebView.
You use WKScriptMessageHandler to make interaction between JavaScript and Swift, when using WKWebView.
ViewController.swift:
import WebKit
class ViewController: NSViewController, WKUIDelegate {
@IBOutlet weak var wkWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "index", withExtension: "html")! //Simplified for testing
let request = URLRequest(url: url)
wkWebView.configuration.preferences.javaScriptEnabled = true
wkWebView.configuration.userContentController.add(self, name: "mySwiftMessage") //<-
wkWebView.load(request)
}
//...
}
extension ViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
switch message.name {
case "mySwiftMessage":
if let callbackName = message.body as? String {
message.webView?.evaluateJavaScript("(callbackName)('Hello From Swift');", completionHandler: nil)
}
default:
break
}
}
}
index.html:
<html>
<body>
<script>
function myCallback(value) {
document.getElementById("i").value = value;
}
</script>
<p>Hello World</p>
<input type=text id='i'/>
<input type=button value='Submit' onclick='window.webkit.messageHandlers.mySwiftMessage.postMessage("myCallback");'>
</body>
</html>
ADDITION
To make WKWebView work on prior iOS's than 11, you just need to instantiate it programmatically:
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var wkWebView: WKWebView! //<- NOT an IBOutlet
override func viewDidLoad() {
super.viewDidLoad()
let webConfig = WKWebViewConfiguration()
webConfig.preferences.javaScriptEnabled = true
webConfig.userContentController.add(self, name: "mySwiftMessage")
wkWebView = WKWebView(frame: self.view.bounds, configuration: webConfig)
view.addSubview(wkWebView)
//You may need to add some constraints...
//And create a better `index.html` for iOS...
let url = Bundle.main.url(forResource: "index", withExtension: "html")!
let request = URLRequest(url: url)
wkWebView.load(request)
}
//...
}
Thank you for the completely working solution.. I would also like to make it work for UIWebView to support iOS 9.0+ since WKWebView is only for iOS11+. Is it possible?
– arun siara.cc
Jan 19 at 8:34
I could not find such an elegant solution for UIWebView. Seems only workarounds are available (such as loading a custom url)
– arun siara.cc
Jan 19 at 8:40
1
You are mistaking the availability ofWKWebView, which is available since iOS 8. Just that you cannot use storyboard forWKWebViewbefore iOS 11. You just need to instantiate yourWKWebViewprogrammatically.
– OOPer
Jan 19 at 10:12
Excellent.. That worked too.. I wish I can upvote you more than once.. Thanks a ton!!
– arun siara.cc
Jan 19 at 10:23
add a comment |
You have found an old article which was written for an ancient WebView of macOS, not for WKWebView.
You use WKScriptMessageHandler to make interaction between JavaScript and Swift, when using WKWebView.
ViewController.swift:
import WebKit
class ViewController: NSViewController, WKUIDelegate {
@IBOutlet weak var wkWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "index", withExtension: "html")! //Simplified for testing
let request = URLRequest(url: url)
wkWebView.configuration.preferences.javaScriptEnabled = true
wkWebView.configuration.userContentController.add(self, name: "mySwiftMessage") //<-
wkWebView.load(request)
}
//...
}
extension ViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
switch message.name {
case "mySwiftMessage":
if let callbackName = message.body as? String {
message.webView?.evaluateJavaScript("(callbackName)('Hello From Swift');", completionHandler: nil)
}
default:
break
}
}
}
index.html:
<html>
<body>
<script>
function myCallback(value) {
document.getElementById("i").value = value;
}
</script>
<p>Hello World</p>
<input type=text id='i'/>
<input type=button value='Submit' onclick='window.webkit.messageHandlers.mySwiftMessage.postMessage("myCallback");'>
</body>
</html>
ADDITION
To make WKWebView work on prior iOS's than 11, you just need to instantiate it programmatically:
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var wkWebView: WKWebView! //<- NOT an IBOutlet
override func viewDidLoad() {
super.viewDidLoad()
let webConfig = WKWebViewConfiguration()
webConfig.preferences.javaScriptEnabled = true
webConfig.userContentController.add(self, name: "mySwiftMessage")
wkWebView = WKWebView(frame: self.view.bounds, configuration: webConfig)
view.addSubview(wkWebView)
//You may need to add some constraints...
//And create a better `index.html` for iOS...
let url = Bundle.main.url(forResource: "index", withExtension: "html")!
let request = URLRequest(url: url)
wkWebView.load(request)
}
//...
}
Thank you for the completely working solution.. I would also like to make it work for UIWebView to support iOS 9.0+ since WKWebView is only for iOS11+. Is it possible?
– arun siara.cc
Jan 19 at 8:34
I could not find such an elegant solution for UIWebView. Seems only workarounds are available (such as loading a custom url)
– arun siara.cc
Jan 19 at 8:40
1
You are mistaking the availability ofWKWebView, which is available since iOS 8. Just that you cannot use storyboard forWKWebViewbefore iOS 11. You just need to instantiate yourWKWebViewprogrammatically.
– OOPer
Jan 19 at 10:12
Excellent.. That worked too.. I wish I can upvote you more than once.. Thanks a ton!!
– arun siara.cc
Jan 19 at 10:23
add a comment |
You have found an old article which was written for an ancient WebView of macOS, not for WKWebView.
You use WKScriptMessageHandler to make interaction between JavaScript and Swift, when using WKWebView.
ViewController.swift:
import WebKit
class ViewController: NSViewController, WKUIDelegate {
@IBOutlet weak var wkWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "index", withExtension: "html")! //Simplified for testing
let request = URLRequest(url: url)
wkWebView.configuration.preferences.javaScriptEnabled = true
wkWebView.configuration.userContentController.add(self, name: "mySwiftMessage") //<-
wkWebView.load(request)
}
//...
}
extension ViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
switch message.name {
case "mySwiftMessage":
if let callbackName = message.body as? String {
message.webView?.evaluateJavaScript("(callbackName)('Hello From Swift');", completionHandler: nil)
}
default:
break
}
}
}
index.html:
<html>
<body>
<script>
function myCallback(value) {
document.getElementById("i").value = value;
}
</script>
<p>Hello World</p>
<input type=text id='i'/>
<input type=button value='Submit' onclick='window.webkit.messageHandlers.mySwiftMessage.postMessage("myCallback");'>
</body>
</html>
ADDITION
To make WKWebView work on prior iOS's than 11, you just need to instantiate it programmatically:
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var wkWebView: WKWebView! //<- NOT an IBOutlet
override func viewDidLoad() {
super.viewDidLoad()
let webConfig = WKWebViewConfiguration()
webConfig.preferences.javaScriptEnabled = true
webConfig.userContentController.add(self, name: "mySwiftMessage")
wkWebView = WKWebView(frame: self.view.bounds, configuration: webConfig)
view.addSubview(wkWebView)
//You may need to add some constraints...
//And create a better `index.html` for iOS...
let url = Bundle.main.url(forResource: "index", withExtension: "html")!
let request = URLRequest(url: url)
wkWebView.load(request)
}
//...
}
You have found an old article which was written for an ancient WebView of macOS, not for WKWebView.
You use WKScriptMessageHandler to make interaction between JavaScript and Swift, when using WKWebView.
ViewController.swift:
import WebKit
class ViewController: NSViewController, WKUIDelegate {
@IBOutlet weak var wkWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "index", withExtension: "html")! //Simplified for testing
let request = URLRequest(url: url)
wkWebView.configuration.preferences.javaScriptEnabled = true
wkWebView.configuration.userContentController.add(self, name: "mySwiftMessage") //<-
wkWebView.load(request)
}
//...
}
extension ViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
switch message.name {
case "mySwiftMessage":
if let callbackName = message.body as? String {
message.webView?.evaluateJavaScript("(callbackName)('Hello From Swift');", completionHandler: nil)
}
default:
break
}
}
}
index.html:
<html>
<body>
<script>
function myCallback(value) {
document.getElementById("i").value = value;
}
</script>
<p>Hello World</p>
<input type=text id='i'/>
<input type=button value='Submit' onclick='window.webkit.messageHandlers.mySwiftMessage.postMessage("myCallback");'>
</body>
</html>
ADDITION
To make WKWebView work on prior iOS's than 11, you just need to instantiate it programmatically:
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var wkWebView: WKWebView! //<- NOT an IBOutlet
override func viewDidLoad() {
super.viewDidLoad()
let webConfig = WKWebViewConfiguration()
webConfig.preferences.javaScriptEnabled = true
webConfig.userContentController.add(self, name: "mySwiftMessage")
wkWebView = WKWebView(frame: self.view.bounds, configuration: webConfig)
view.addSubview(wkWebView)
//You may need to add some constraints...
//And create a better `index.html` for iOS...
let url = Bundle.main.url(forResource: "index", withExtension: "html")!
let request = URLRequest(url: url)
wkWebView.load(request)
}
//...
}
edited Jan 19 at 10:09
answered Jan 19 at 8:12
OOPerOOPer
34.4k46385
34.4k46385
Thank you for the completely working solution.. I would also like to make it work for UIWebView to support iOS 9.0+ since WKWebView is only for iOS11+. Is it possible?
– arun siara.cc
Jan 19 at 8:34
I could not find such an elegant solution for UIWebView. Seems only workarounds are available (such as loading a custom url)
– arun siara.cc
Jan 19 at 8:40
1
You are mistaking the availability ofWKWebView, which is available since iOS 8. Just that you cannot use storyboard forWKWebViewbefore iOS 11. You just need to instantiate yourWKWebViewprogrammatically.
– OOPer
Jan 19 at 10:12
Excellent.. That worked too.. I wish I can upvote you more than once.. Thanks a ton!!
– arun siara.cc
Jan 19 at 10:23
add a comment |
Thank you for the completely working solution.. I would also like to make it work for UIWebView to support iOS 9.0+ since WKWebView is only for iOS11+. Is it possible?
– arun siara.cc
Jan 19 at 8:34
I could not find such an elegant solution for UIWebView. Seems only workarounds are available (such as loading a custom url)
– arun siara.cc
Jan 19 at 8:40
1
You are mistaking the availability ofWKWebView, which is available since iOS 8. Just that you cannot use storyboard forWKWebViewbefore iOS 11. You just need to instantiate yourWKWebViewprogrammatically.
– OOPer
Jan 19 at 10:12
Excellent.. That worked too.. I wish I can upvote you more than once.. Thanks a ton!!
– arun siara.cc
Jan 19 at 10:23
Thank you for the completely working solution.. I would also like to make it work for UIWebView to support iOS 9.0+ since WKWebView is only for iOS11+. Is it possible?
– arun siara.cc
Jan 19 at 8:34
Thank you for the completely working solution.. I would also like to make it work for UIWebView to support iOS 9.0+ since WKWebView is only for iOS11+. Is it possible?
– arun siara.cc
Jan 19 at 8:34
I could not find such an elegant solution for UIWebView. Seems only workarounds are available (such as loading a custom url)
– arun siara.cc
Jan 19 at 8:40
I could not find such an elegant solution for UIWebView. Seems only workarounds are available (such as loading a custom url)
– arun siara.cc
Jan 19 at 8:40
1
1
You are mistaking the availability of
WKWebView, which is available since iOS 8. Just that you cannot use storyboard for WKWebView before iOS 11. You just need to instantiate your WKWebView programmatically.– OOPer
Jan 19 at 10:12
You are mistaking the availability of
WKWebView, which is available since iOS 8. Just that you cannot use storyboard for WKWebView before iOS 11. You just need to instantiate your WKWebView programmatically.– OOPer
Jan 19 at 10:12
Excellent.. That worked too.. I wish I can upvote you more than once.. Thanks a ton!!
– arun siara.cc
Jan 19 at 10:23
Excellent.. That worked too.. I wish I can upvote you more than once.. Thanks a ton!!
– arun siara.cc
Jan 19 at 10:23
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54264550%2fgetting-invokeundefinedmethodfromwebscript-to-work-in-swift%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown