Migrate UIWebView to WKWebView

iOS Nov 03, 2020
ITMS-90809: Deprecated API Usage - Apple will stop accepting submissions of app updates that use UIWebView APIs starting from December 2020. See https://developer.apple.com/documentation/uikit/uiwebview for more information.

Có thể bạn thừa biết rằng từ 01/04/2020, Apple sẽ không chấp nhận bất kỳ bản cập nhập hoặc ứng dụng mới nào đưa lên store mà có chưa UIWebView.

Với các ứng dụng mới thì khá đơn giản là không sử dụng UIWebView mà sử dụng WKWebView để phát triển browser in-app.
Với các ứng dụng đã và đang phát triển thì sao?
- Kiểm tra xem có đang sử dụng UIWebView trong code hoặc trong 3rd party libraries hay không.
- Thay thế UIWebView bằng WKWebView.

Kiểm tra code có sử dụng UIWebView

Để kiểm tra trong code hoặc thư viện đang sử dụng có chưa UIWebView một cách hiệu quả thì chúng ta có thể chạy command grep để kiểm tra.
Đầu tiên cần mở Terminal chạy lệnh cd đến thư mục chứa project, sau đó chạy command:

grep -r "UIWebView" .

Nếu trong project có chưa keyword UIWebView sẽ được in ra file nào ở text nào chứa từ khóa này

Thay thế UIWebView bằng WKWebView

Sau khi kiểm tra kết quả thì chúng ta có thể dễ dàng thấy các code trong dự án hay các thư viện đang sử dụng UIWebView.

Với các thư viện có chứa UIWebView thì phương án xử lý là cố gắng update version cho các thư viện đó. Đến hiện tại thì hầu hết các thư viện đã support việc remove UIWebView khỏi thư viện. Trong trường hợp xấu nhất là không có version support cho việc này thì cần tìm thư viện thay thế và đánh giá phạm vi ảnh hưởng.

Với các class đang sử dụng UIWebView thì ngoài việc thay thế UIWebView bằng WKWebView thì đồng thời cũng cần migrate delegate của UIWebView.
WKWebView có 2 delegates:
- WKNavigationDelegate dùng cho việc xử lý các quyết định liên quan đến điều hướng.
- WKUIDelegate dùng cho quản lý cửa sổ giao diện web cùng với phải hồi đến Javascript được thực thi trong page.

Với các class đang sử dụng các method của UIWebViewDelegate

webView(_:shouldStartLoadWith:navigationType:)
webViewDidStartLoad(_:)
webViewDidFinishLoad(_:)
webView(_:didFailLoadWithError:)

Có thể thay thế tương ứng với các method của WKNavigationDelegate như sau:

webView(_:decidePolicyFor action:decisionHandler:)
webView(_:didStartProvisionalNavigation:)
webView(_:didFinish:)
webView(_:didFail:withError:)

Vấn đề gặp phải

Ở trong một dự án gần đây có yêu cầu thay thế UIWebView bằng WKWebView có gặp phải một lỗi của WKWebView.
Trong project đó có một chức năng đăng nhập bằng webview và đang thực hiện bằng cơ chế: website đó phục vụ cho mục đích login, khi người dùng nhấn login thì sẽ thực hiện mở một website khác bằng request với phương thức POST.
Ứng dụng sẽ kiểm tra khi website thực hiện request đến một địa chỉ url định sẵn thì biết đó là request login, sẽ chỉnh sửa lại header để thêm giá trị thông báo cho website đây là login từ app mobile, website khi nhận được request và biết từ mobile thì sẽ redirect đến một địa chỉ cụ thể phục vụ cho chức năng login app mobile.
Khi ứng dụng nhận được sự kiện website redirect đến page login thành công thì sẽ chạy javascript để lấy các thông tin cần thiết.

Vậy vấn đề gặp phải khi chuyển sang dùng WKWebView là gì?
Sau khi thay thế bằng WKWebView thì phát hiện một bug lạ là khi thực hiện login bằng website với method POST thì http body bị rỗng (nil). Lỗi này được xác nhận đang là vấn đề gặp phải của WKWebView.

Cách xử lý ra sao?

Một trong cách xử lý hữu hiệu nhất là thay đổi việc xử lý điều hướng bằng cách thực hiện request bằng method POST, thì có thể gợi ý website sẽ call api thực hiện việc login, sau khi thành công thì sử dụng Webkit để truyền event cho native app.

Cụ thể thì các bạn có thể tham khảo bài viết tại đây để hiểu cách thực hiện cụ thể như thế nào.

Tags

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.