Hiểu rõ từ cơ bản
Để hiểu sâu hơn, bạn hãy tải ngay source code demo tại đây: https://github.com/oNguyenVanThieu/UIWebView Hãy chạy thử và xem kỹ log để hiểu rõ hơn.
Đầu tiên, hãy khai báo extension ViewController là UIWebViewDelegate. Ta có các kiểu tương ứng của navigationType như sau:
public enum UIWebViewNavigationType : Int {
case linkClicked // khi bạn click vào link trong webView
case formSubmitted
case backForward // khi bạn sử dụng webView.goBack() hoặc webView.goForward()
case reload // khi bạn sử dụng webView.reload()
case formResubmitted
case other // khi bạn tự gọi webView.loadRequest
}
Trong hàm webView(_:shouldStartLoadWith:navigationType), tham số request là request hiện tại mà webView chuẩn bị thực hiện. webView sẽ chứa request của lần trước, ban đầu thì nó sẽ là nil. Nếu return true, request sẽ được thực hiện, còn false thì không.
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
print("1.1. shouldStartLoadWith navigationType ", navigationType.rawValue)
print("1.2. shouldStartLoadWith request ", request.url?.absoluteString)
print("1.3. shouldStartLoadWith webView ", webView.request?.url?.absoluteString)
return true
}
Trong hàm webViewDidStartLoad(_:), webView chứa request sau khi thực hiện thành công.
func webViewDidStartLoad(_ webView: UIWebView) {
print("2. webViewDidStartLoad webView ", webView.request?.url?.absoluteString)
indicator.startAnimating()
}
Trong hàm webViewDidFinishLoad(_:), webView chứa request sau khi thực hiện thành công.
func webViewDidFinishLoad(_ webView: UIWebView) {
print("3. webViewDidFinishLoad webView ", webView.request?.url?.absoluteString)
indicator.stopAnimating()
}
Trong hàm webView(_:didFailLoadWithError:), webView chứa request khi thực hiện gặp lỗi.
func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
print("4. didFailLoadWithError webView ", webView.request?.url?.absoluteString)
indicator.stopAnimating()
}
Dù khi mất mạng, bạn vẫn hoàn toàn có thể sử dụng webView.goBack() và webView.goForward(). Tuy nhiên, khi mất mạng, hàm webViewDidStartLoad sẽ không được thực hiện.
Thêm một đoạn code làm màu nhẹ để khiến trang không cuộn quá khi ở trên cùng hay dưới cùng. Điều này nhằm lừa tình người dùng và khiến họ không biết đang ở trong WebView hay Native :v
private func prepareWebView() {
webView.scrollView.bounces = false
webView.scalesPageToFit = false
webView.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal
}
Các debug với Safari
Bạn có thể sử dụng Safari để debug UIWebView. Truy cập vào Develop của Safari, sau đó chọn thiết bị và link muốn xem. Ở chế độ này, bạn có thể xem rất nhiều thông tin như link hiện tại, giá trị của cookie, v.v…
Click vào tab Storage để xem chi tiết Cookie, Local Storage, Session Storeage
Click vào tab Resource để xem thông tin chi tiết của một link.
Cách thực thi lệnh JavaScript
Để thực thi một lệnh JavaScript, ta sử dụng đoạn mã sau:
let js = "document.title;";
let value = webView.stringByEvaluatingJavaScript(from: js)
print(value)
Biến js trên là một câu lệnh JavaScript bạn muốn thực hiện qua hàm stringByEvaluatingJavaScript. Kết quả trả về là một chuỗi tùy chọn.
Chặn bắt, thay đổi URLRequest
Ví dụ, đoạn code sau kiểm tra xem có phải là link “https://developer.apple.com/documentation/uikit/views_and_controls” không. Nếu đúng, request đó sẽ bị chặn và thay bằng link “https://www.google.com.vn/“.
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if let currentUrl = request.url?.absoluteString, currentUrl == "https://developer.apple.com/documentation/uikit/views_and_controls" {
loadURL("https://www.google.com.vn/")
return false
}
return true
}
Còn đoạn code sau tạo một URLRequest từ một đường dẫn, sau đó thực hiện request đó bằng webView.loadRequest.
func loadURL(_ urlString: String) {
if let url = URL(string: urlString) {
let req = URLRequest(url: url)
webView.loadRequest(req)
}
}
Vậy là qua ví dụ đơn giản này, bạn có thể thực hiện một hành động sau khi click vào UIWebView và xử lý nó trong phần native. Ví dụ, bạn có thể click vào nút Share của UIWebView, sau đó chặn request lại và thực hiện hành động đó trong native.
Ngoài ra, bạn có thể giữ lại URLRequest và sau đó sử dụng webView.loadRequest sau một thời điểm nào đó. Ví dụ, người dùng đang đăng nhập trên UIWebView nhưng bị mất mạng. Bạn có thể giữ lại URLRequest đó và thực hiện webView.loadRequest khi có mạng trở lại (Điều này cũng áp dụng cho cả method kiểu post và get. Hãy thử với bạn bè dev Android của bạn xem họ có thể làm tương tự không? :v)
Một điều hay nữa khi bạn hiểu rõ cách chặn bắt URLRequest là bạn có thể tự xử lý việc lưu trữ lịch sử của webView mà không cần phải sử dụng webView.goBack(), webView.goForward() hoặc webView.reload() nữa. Bạn có thể tự xử lý với webView.loadRequest của bạn và có một mảng lưu trữ lại các URLRequest của WebView. Lưu ý rằng, có thể mở nhiều URLRequest khi mở link từ WebView.
Bài viết được chỉnh sửa bởi HEFC. Đọc thêm tại hefc.edu.vn.