Я довольно новичок в разработке Swift, и у меня есть гибридное приложение, которое я разрабатываю, к которому я подключил аутентификацию. Когда пользователь аутентифицируется датчиком отпечатков пальцев на устройстве, я хочу запустить JS или иным образом взаимодействовать с WKWebView ... но по какой-то причине я не могу заставить его работать. Я могу делать простые вещи, такие как изменение окна HREF ... но если я делаю что-то более сложное, это либо ничего не делает, либо терпит неудачу.Swift: using оценитьJavascript
Вот код моего ViewController:
import UIKit
import WebKit
import LocalAuthentication
class ViewController: UIViewController, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate {
@IBOutlet var containerView : UIView! = nil
// @IBOutlet weak var webView: UIWebView!
var webView: WKWebView?
var contentController = WKUserContentController();
@IBOutlet var activityIndicatorView: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
// append the userAgent and ensure it contains our browser detect regEx
let userAgent = UIWebView().stringByEvaluatingJavaScriptFromString("navigator.userAgent")! + " iPad"
NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent" : userAgent])
// add JS content controller
var config = WKWebViewConfiguration()
config.userContentController = contentController
// instantiate the web view
let webView = WKWebView(frame: CGRectZero, configuration: config)
webView.setTranslatesAutoresizingMaskIntoConstraints(false)
webView.navigationDelegate = self
view.addSubview(webView)
// customize sizing
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[webView]|", options: NSLayoutFormatOptions.allZeros, metrics: nil, views: ["webView": webView]))
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[webView]|", options: NSLayoutFormatOptions.allZeros, metrics: nil, views: ["webView": webView]))
// open the URL for the app
let urlPath = "http://im_a_url"
let url: NSURL = NSURL(string: urlPath)!
let request = NSURLRequest(URL: url)
webView.loadRequest(request)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func webView(webView: WKWebView!, didStartProvisionalNavigation navigation: WKNavigation!) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
}
func webView(webView: WKWebView!, didFinishNavigation navigation: WKNavigation!) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
// trigger authentication
authenticateUser()
}
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
}
func logInWithStoredCredentials() {
println("successful auth - log in");
// TO DO - use core data to stor user credentials
webView!.evaluateJavaScript("document.getElementById('anonymousFormSubmit').click();", nil)
}
func authenticateUser() {
// Get the local authentication context.
let context = LAContext()
// Declare a NSError variable.
var error: NSError?
// Set the reason string that will appear on the authentication alert.
var reasonString = "Authentication is needed to access aware360Suite."
// Check if the device can evaluate the policy.
if context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error) {
[context .evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString, reply: { (success: Bool, evalPolicyError: NSError?) -> Void in
if success {
self.logInWithStoredCredentials()
// self.webView?.evaluateJavaScript("document.getElementById('auiAuthSubmitBtn').click();", nil)
}
else{
// If authentication failed then show a message to the console with a short description.
// In case that the error is a user fallback, then show the password alert view.
println(evalPolicyError?.localizedDescription)
switch evalPolicyError!.code {
case LAError.SystemCancel.rawValue:
println("Authentication was cancelled by the system")
case LAError.UserCancel.rawValue:
println("Authentication was cancelled by the user")
case LAError.UserFallback.rawValue:
println("User selected to enter custom password")
// self.showPasswordAlert()
default:
println("Authentication failed")
// self.showPasswordAlert()
}
}
})]
}
else{
// If the security policy cannot be evaluated then show a short message depending on the error.
switch error!.code{
case LAError.TouchIDNotEnrolled.rawValue:
println("TouchID is not enrolled")
case LAError.PasscodeNotSet.rawValue:
println("A passcode has not been set")
default:
// The LAError.TouchIDNotAvailable case.
println("TouchID not available")
}
}
}
}
Проблема заключается в успешном методе аутентификации:
func logInWithStoredCredentials() {
println("successful auth - log in");
// TO DO - use core data to use stored user credentials
webView!.evaluateJavaScript("document.getElementById('anonymousFormSubmit').click();", nil)
}
Я не могу показаться, чтобы получить дескриптор Webview здесь. Если я попытаюсь на самом деле оценить сценарий здесь, это вызывает следующую ошибку:
2015-02-10 17:07:32.912 A360[2282:462860] -[UIWebView evaluateJavaScript:completionHandler:]: unrecognized selector sent to instance 0x1741897f0
2015-02-10 17:07:32.916 A360[2282:462860] <NSXPCConnection: 0x178103960> connection to service named com.apple.CoreAuthentication.daemon: Warning: Exception caught during decoding of received reply to message 'evaluatePolicy:options:reply:', dropping incoming message and calling failure block.
Exception: -[UIWebView evaluateJavaScript:completionHandler:]: unrecognized selector sent to instance 0x1741897f0
Я совсем не в порядке. Я знаю, что у меня нет надлежащего описатель WebView здесь, потому что я знаю, что если я попытаюсь операцию, как это сразу же после того, как была успешной навигации с точки зрения, она будет прекрасно работать, например:
func webView(webView: WKWebView!, didFinishNavigation navigation: WKNavigation!) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
webView.evaluateJavaScript("document.getElementById('anonymousFormSubmit').click();", nil)
}
Так ясно, что в моей функции logInWithStoredCredentials он потерял контекст webView.
Как я могу получить правильную ручку для webView в моей функции logInWithStoredCredentials?
Извините, все - я знаю, что это довольно простой вопрос, но я уже несколько часов стучаю головой против него, и это очень важная проблема, которую я должен решить быстро.
Взгляните на эту новую [библиотеку] (https://github.com/coshx/caravel), это может вам помочь;) –