岳陽網(wǎng)站開發(fā)商城網(wǎng)絡(luò)推廣項目計劃書
文章目錄
- 前言
- 開發(fā)環(huán)境
- 問題描述
- 問題分析
- 解決方案
- 最后
前言
最近維護一個老項目時遇到的問題。說起這老項目我就有點頭疼,一個快十年前的項目,這么說你可能不覺得有什么,但是你想想Swift也才發(fā)布不到十年(2014年6月發(fā)布,現(xiàn)2023年12月)。
開發(fā)環(huán)境
- Xcode: 15.1
- iOS: 17.2
問題描述
項目運行在iOS 17.2設(shè)備時,應(yīng)用內(nèi)網(wǎng)頁無法成功獲取設(shè)置后的UserAgent
。
項目中設(shè)置UserAgent
的關(guān)鍵源碼:
[self.webView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id result, NSError *error) {NSString *userAgent = [NSString stringWithFormat:@"%@", result];NSString *newUserAgent = [userAgent stringByAppendingString:@" App/1.0.0"];[[NSUserDefaults standardUserDefaults] registerDefaults:@{@"UserAgent": newUserAgent}];
}];
問題分析
從項目源碼看,設(shè)置UserAgent
是通過NSUserDefaults
實現(xiàn)的。大致操作如下:
- 首先應(yīng)用啟動后創(chuàng)建一個
WKWebView
實例對象,無需加載任何網(wǎng)頁 - 然后通過
navigator.userAgent
獲取當(dāng)前的UserAgent
并修改 - 接著調(diào)用
registerDefaults
方法將修改后的UserAgent
注冊到NSUserDefaults
,成為應(yīng)用的默認(rèn)設(shè)置 - 最后銷毀該
WKWebView
實例對象
經(jīng)過以上操作,后續(xù)創(chuàng)建WKWebView
實例對象時都能從NSUserDefaults
中獲取到修改后的UserAgent
用于初始化,從而實現(xiàn)全局設(shè)置。需要注意一點,registerDefaults
方法設(shè)置默認(rèn)值的操作不會進(jìn)行持久化存儲,所以應(yīng)用每次啟動都需要設(shè)置一遍。
雖然理了一遍設(shè)置邏輯感覺沒什么問題,但是這個方法有點老了,現(xiàn)在一般通過customUserAgent
屬性設(shè)置,難道這個方法過時了?
為了排除其他可能存在的干擾,新建一個iOS項目用于測試,源碼如下:
import UIKit
import WebKitclass ViewController: UIViewController, WKNavigationDelegate {private let htmlString = """<html><head><meta name="viewport" content="width=device-width"><style>button {font-size: 24px;}</style><script>function getUserAgent() {var userAgent = navigator.userAgent;var paragraph = document.createElement('p');paragraph.textContent = 'UserAgent: ' + userAgent;document.body.appendChild(paragraph);}</script></head><body style="text-align: center;"><button οnclick="getUserAgent()">獲取 UserAgent</button></body></html>"""private var webView: WKWebView!override func viewDidLoad() {super.viewDidLoad()// 在WKWebView初始化前設(shè)置UserAgentUserDefaults.standard.register(defaults: ["UserAgent": "App/1.0.0"])// 創(chuàng)建WKWebViewlet webViewConfiguration = WKWebViewConfiguration()webView = WKWebView(frame: view.bounds, configuration: webViewConfiguration)webView.navigationDelegate = selfview.addSubview(webView)// 加載HTMLwebView.loadHTMLString(htmlString, baseURL: nil)}
}
iOS 17.2測試結(jié)果:
iOS 16.4測試結(jié)果:
實測iOS 17.0和iOS 17.2測試結(jié)果一樣,現(xiàn)在可以確定從iOS 17開始,通過NSUserDefaults
設(shè)置UserAgent
都無法生效。初步判斷,這個設(shè)置方法在iOS 17及以上過時了,個人猜測可能是WKWebView
初始化時不再從NSUserDefaults
獲取默認(rèn)值導(dǎo)致的(今天天太冷了,實在扛不住,后面有機會再翻翻相關(guān)源碼嘗試驗證猜測)。
既然這個方法失效了,那在iOS 17上通過customUserAgent
屬性設(shè)置能正常生效嗎?
對前面的測試源碼做簡單修改,頁面加載完成后自動獲取一次未修改的UserAgent
,然后再修改UserAgent
并通過customUserAgent
屬性設(shè)置,接著手動點擊按鈕獲取一次UserAgent
,最后對比兩次獲取結(jié)果判斷是否設(shè)置成功。
import UIKit
import WebKitclass ViewController: UIViewController, WKNavigationDelegate {private let htmlString = """<html><head><meta name="viewport" content="width=device-width"><style>button {font-size: 24px;}</style><script>function getUserAgent() {var userAgent = navigator.userAgent;var paragraph = document.createElement('p');paragraph.textContent = 'UserAgent: ' + userAgent;document.body.appendChild(paragraph);}/* 頁面加載完成后獲取一次UserAgent */window.onload = function() {getUserAgent();};</script></head><body style="text-align: center;"><button οnclick="getUserAgent()">獲取 UserAgent</button></body></html>"""private var webView: WKWebView!override func viewDidLoad() {super.viewDidLoad()// 創(chuàng)建WKWebViewlet webViewConfiguration = WKWebViewConfiguration()webView = WKWebView(frame: view.bounds, configuration: webViewConfiguration)webView.navigationDelegate = selfview.addSubview(webView)// 加載HTMLwebView.loadHTMLString(htmlString, baseURL: nil)}func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {// 獲取當(dāng)前的UserAgentwebView.evaluateJavaScript("navigator.userAgent") { (result, error) inguard let userAgent = result as? String else {return}let newUserAgent = userAgent + " App/1.0.0"// 設(shè)置UserAgentwebView.customUserAgent = newUserAgent}}
}
測試結(jié)果:
從測試結(jié)果看,通過customUserAgent
屬性設(shè)置UserAgent
一切正常。不過這種方法不好實現(xiàn)全局設(shè)置,每次創(chuàng)建新的WKWebView
實例對象都需要再設(shè)置一遍。
解決方案
通過NSUserDefaults
設(shè)置UserAgent
改為通過customUserAgent
屬性設(shè)置UserAgent
,更多詳情請參考前面的問題分析。
最后
如果這篇文章對你有所幫助,點贊👍收藏🌟支持一下吧,謝謝~
本篇文章由@crasowas發(fā)布于CSDN。