はじめに
こんにちはsuzukiです。今回はWKWebViewのCookieの更新について、継続的に監視する方法について整理しました。
differenceという機能を利用して配列の中身を取得しています。
リリースする資産に追加というよりはデバッグしている際にCoookieの更新が想定通りであるかの確認を行うなどの際
WKWebViewのCookieの監視
Cookieの更新を取得する
WKHTTPCookieStoreObserverのcookieDidChangeを利用してCookieの更新を検知します。
利用するためには更新を取得したいクラスでWKHTTPCookieStoreObserverを批准しCookieDidChangeを実装し、httpCookieStoreのaddで監視するオブジェクトを追加します。
下記のコードはすべてのCookieをログ表示していますが、更新のたびにCookieの全量を出力するため、使い勝手があまり良くないです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import WebKit public class CookieChecker: NSObject, WKHTTPCookieStoreObserver { // Sync WKWebView Cookies to HTTPCookieStorage static let shared = CookieChecker() public func cookiesDidChange(in cookieStore: WKHTTPCookieStore) { cookieStore.getAllCookies { cookies in cookies.forEach { cookie in print(cookie) } } } public func startCookieCheck(){ WKWebsiteDataStore.default().httpCookieStore.add(self) } } |
differenceを利用して必要なCookieの更新を取得する
あまり新しい機能ではないのですが、配列の比較を行うdifferenceを利用することによって、変更のあったCookieを取得することができます。
differenceは配列の比較を行い、追加された要素、削除された要素を取得することができます。
insertionsに追加された要素、removalsに削除された要素が追加されます。
先ほどのコードを下記のように変更することにより、変更された内容の取得がしやすくなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | var beforeCookie : [HTTPCookie] = [] public func cookiesDidChange(in cookieStore: WKHTTPCookieStore) { cookieStore.getAllCookies { cookies in print(cookieStore) let diff = cookies.difference(from: self.beforeCookie) for change in diff { switch change { case let .insert(offset, element, _): print("\(offset)番目に要素\(element.name):\( element.value )を追加") case let .remove(offset, element, _): print("\(offset)番目に要素\(element.name):\( element.value )を削除") } } self.beforeCookie = cookies } } |
ログとしては上記の追加されたCookieのNameとValueを出力します。もし詳細な情報が必要であれば、elementをそのまま出力すれば確認できます。
必要Cookieだけ出力したい場合は適宜if文の追加を行うことで、自分の監視を行いたいCookieの出力が可能です。
おまけ
differenceの挙動について
differenceの比較はプリミティブな値とClassによって異なります。
プリミティブな値では値の比較が行われます。
クラスの場合は少なくとも、Equatableに準拠している必要があります。
Equatableに準拠するためには下記の==を定義する必要あります。下記のコードであればクラスの参照が同じであればtrue異なればfalseです。
1 2 3 | static func == (lhs: Book, rhs: Book) -> Bool { lhs === rhs } |
もしNSObjectを継承しているクラスの場合はデフォルトで上記のコードと同様参照の比較なのですが、もし特定の値の更新を無視したい場合などは、下記のようにisEqualをオーバーライドすることによって自由に変更が可能です。
1 2 3 | override func isEqual(_ object: Any?) -> Bool { } |
変更は可能なのですが、既存のコードで比較を利用している場合は上記のコードの追加により挙動が変わる可能性があるので、differenceで比較後に出力したい内容を絞り込むのがいいのかなと思います。
さいごに
Cookie関係で問題が起きた時、みなくては行けない箇所が複数にまたがり、また確認も何度もしなくてはいけない印象です。
どうしても情報量が多くなるので、欲しい情報だけ取得する手段があると助かります。