如何让Swift与Webview进行交互?

时间:2016-02-18 11:59:31

标签: ios xcode swift webview

我正在使用Xcode构建一个基本的iOS应用程序,主要只包含一个带有我的Web应用程序的webview。

我想知道在登录时是否有一种方法可以将用户用户名保存到设备存储中,以便下次打开应用时可以自动输入。由于该应用程序是一个webview,我不相信有一种方法可以让用户登录(就像其他主要应用程序一样,例如Facebook),所以我认为自动填充用户名对他们有益。

我发现this question and answer可以解决我的问题,尽管它可以解决我的问题。目标C。

我目前的尝试,绝对没有:

let savedUsername = "testusername"

let loadUsernameJS = "document.getElementById(\"mainLoginUsername\").value = " + savedUsername + ";"

self.Webview.stringByEvaluatingJavaScriptFromString(loadUsernameJS)

这是Swift的可能吗?

3 个答案:

答案 0 :(得分:4)

用于存储密码,您应该使用密钥链,特别是Web凭据。如果操作正确,这将允许您的应用程序使用通过Safari输入的任何现有钥匙串条目,并且还允许Safari通过您的应用程序保存时访问密码。

下面提供的设置和检索代码:

private let domain = "www.youdomain.com"

func saveWebCredentials(username: String, password: String, completion: Bool -> Void) {
    SecAddSharedWebCredential(domain, username, password) { error in
        guard error == nil else { print("error saving credentials: \(error)"); return completion(false) }
        completion(true)
    }
}

func getExistingWebCredentials(completion: ((String, String)?, error: String?) -> Void) {
    SecRequestSharedWebCredential(domain, nil) { credentials, error in
        // make sure we got the credentials array back
        guard let credentials = credentials else { return completion(nil, error: String(CFErrorCopyDescription(error))) }

        // make sure there is at least one credential
        let count = CFArrayGetCount(credentials)
        guard count > 0 else { return completion(nil, error: "no credentials stored") }

        // extract the username and password from the credentials dict
        let credentialDict = unsafeBitCast(CFArrayGetValueAtIndex(credentials, 0), CFDictionaryRef.self)
        let username = CFDictionaryGetValue(credentialDict, unsafeBitCast(kSecAttrAccount, UnsafePointer.self))
        let password = CFDictionaryGetValue(credentialDict, unsafeBitCast(kSecSharedPassword, UnsafePointer.self))

        // return via completion block
        completion((String(unsafeBitCast(username, CFStringRef.self)), String(unsafeBitCast(password, CFStringRef.self))), error: nil)
    }
}

使用如下:

// save the credentials
saveWebCredentials("hello", password: "world", completion: { success in

    // retrieve the credentials
    getExistingWebCredentials { credentials, error in
        guard let credentials = credentials else { print("Error: \(error)"); return }
        print("got username: \(credentials.0) password: \(credentials.1)")
    }
})

<强>更新

建议切换到使用WKWebView,以便轻松拉出响应标头。这是样板代码:

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let webView = WKWebView(frame: self.view.bounds)
        webView.navigationDelegate = self
        self.view.addSubview(webView)

        webView.loadRequest(NSURLRequest(URL: NSURL(string: "https://www.google.com")!))
    }

    func webView(webView: WKWebView, decidePolicyForNavigationResponse navigationResponse: WKNavigationResponse, decisionHandler: (WKNavigationResponsePolicy) -> Void) {
        // make sure the response is a NSHTTPURLResponse
        guard let response = navigationResponse.response as? NSHTTPURLResponse else { return decisionHandler(.Allow) }

        // get the response headers
        let headers = response.allHeaderFields
        print("got headers: \(headers)")

        // allow the request to continue
        decisionHandler(.Allow);
    }
}

答案 1 :(得分:1)

您的代码无效,因为您没有用引号括起savedUsername

你应该改为:

let loadUsernameJS = "document.getElementById(\"mainLoginUsername\").value = \"\(savedUsername)\";"

另外,this library might help you

答案 2 :(得分:0)

您没有将字符串传递给JavaScript,您应该将该变量封装在其他引号中

let loadUsernameJS = "document.getElementById(\"mainLoginUsername\").value = \"" + savedUsername + "\";"

let loadUsernameJS = "document.getElementById('mainLoginUsername').value = '" + savedUsername + "';"