iOS问题记录 - iOS 17通过NSUserDefaults设置UserAgent无效

news2024/11/25 14:41:27

文章目录

  • 前言
  • 开发环境
  • 问题描述
  • 问题分析
  • 解决方案
  • 最后


前言

最近维护一个老项目时遇到的问题。说起这老项目我就有点头疼,一个快十年前的项目,这么说你可能不觉得有什么,但是你想想Swift也才发布不到十年(2014年6月发布,现2023年12月)。

开发环境

  • Xcode: 15.1
  • iOS: 17.2

问题描述

项目运行在iOS 17.2设备时,应用内网页无法成功获取设置后的UserAgent

项目中设置UserAgent的关键源码:

[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}];
}];

问题分析

从项目源码看,设置UserAgent是通过NSUserDefaults实现的。大致操作如下:

  1. 首先应用启动后创建一个WKWebView实例对象,无需加载任何网页
  2. 然后通过navigator.userAgent获取当前的UserAgent并修改
  3. 接着调用registerDefaults方法将修改后的UserAgent注册到NSUserDefaults,成为应用的默认设置
  4. 最后销毁该WKWebView实例对象

经过以上操作,后续创建WKWebView实例对象时都能从NSUserDefaults中获取到修改后的UserAgent用于初始化,从而实现全局设置。需要注意一点,registerDefaults方法设置默认值的操作不会进行持久化存储,所以应用每次启动都需要设置一遍。

虽然理了一遍设置逻辑感觉没什么问题,但是这个方法有点老了,现在一般通过customUserAgent属性设置,难道这个方法过时了?

为了排除其他可能存在的干扰,新建一个iOS项目用于测试,源码如下:

import UIKit
import WebKit

class 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初始化前设置UserAgent
        UserDefaults.standard.register(defaults: ["UserAgent": "App/1.0.0"])
        
        // 创建WKWebView
        let webViewConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: view.bounds, configuration: webViewConfiguration)
        webView.navigationDelegate = self
        view.addSubview(webView)
        
        // 加载HTML
        webView.loadHTMLString(htmlString, baseURL: nil)
    }
}

iOS 17.2测试结果:

screenshot1

iOS 16.4测试结果:

screenshot2

实测iOS 17.0和iOS 17.2测试结果一样,现在可以确定从iOS 17开始,通过NSUserDefaults设置UserAgent都无法生效。初步判断,这个设置方法在iOS 17及以上过时了,个人猜测可能是WKWebView初始化时不再从NSUserDefaults获取默认值导致的(今天天太冷了,实在扛不住,后面有机会再翻翻相关源码尝试验证猜测)。

既然这个方法失效了,那在iOS 17上通过customUserAgent属性设置能正常生效吗?

对前面的测试源码做简单修改,页面加载完成后自动获取一次未修改的UserAgent,然后再修改UserAgent并通过customUserAgent属性设置,接着手动点击按钮获取一次UserAgent,最后对比两次获取结果判断是否设置成功。

import UIKit
import WebKit

class 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()
        
        // 创建WKWebView
        let webViewConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: view.bounds, configuration: webViewConfiguration)
        webView.navigationDelegate = self
        view.addSubview(webView)
        
        // 加载HTML
        webView.loadHTMLString(htmlString, baseURL: nil)
    }
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        // 获取当前的UserAgent
        webView.evaluateJavaScript("navigator.userAgent") { (result, error) in
            guard let userAgent = result as? String else {
                return
            }
            let newUserAgent = userAgent + " App/1.0.0"
            // 设置UserAgent
            webView.customUserAgent = newUserAgent
        }
    }
}

测试结果:

screenshot3

从测试结果看,通过customUserAgent属性设置UserAgent一切正常。不过这种方法不好实现全局设置,每次创建新的WKWebView实例对象都需要再设置一遍。

解决方案

通过NSUserDefaults设置UserAgent改为通过customUserAgent属性设置UserAgent,更多详情请参考前面的问题分析。

最后

如果这篇文章对你有所帮助,点赞👍收藏🌟支持一下吧,谢谢~


本篇文章由@crasowas发布于CSDN。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1321247.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DS排序--快速排序

Description 给出一个数据序列&#xff0c;使用快速排序算法进行从小到大的排序 排序方式&#xff1a;以区间第一个数字为枢轴记录 输出方式&#xff1a;每一步区间排序&#xff0c;都输出整个数组 –程序要求– 若使用C只能include一个头文件iostream&#xff1b;若使用C…

深度学习笔记_7经典网络模型LSTM解决FashionMNIST分类问题

1、 调用模型库&#xff0c;定义参数&#xff0c;做数据预处理 import numpy as np import torch from torchvision.datasets import FashionMNIST import torchvision.transforms as transforms from torch.utils.data import DataLoader import torch.nn.functional as F im…

2000年AMC8数学竞赛中英文真题典型考题、考点分析和答案解析

今天是2023年12月19日&#xff0c;距离2024年的AMC8正式考试倒计时一个月。 从战争中学习战争最有效。前几天&#xff0c;六分成长分析了2023年、2022年、2020、2019、2018、2017的AMC8真题的典型考题、考点和详细答案解析。 今天我们不再从2016年分析&#xff0c;来看看更早…

pytorch文本分类(三)模型框架(DNNtextCNN)

pytorch文本分类&#xff08;三&#xff09;模型框架&#xff08;DNN&textCNN&#xff09; 原任务链接 目录 pytorch文本分类&#xff08;三&#xff09;模型框架&#xff08;DNN&textCNN&#xff09;1. 背景知识深度学习 2. DNN2.1 从感知器到神经网络2.2 DNN的基本…

避坑指南:uni-forms表单在uni-app中的实践经验

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;uni-app篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:uni-app中forms表单的避坑指南篇 该篇章已被前端圈子收录,点此处进入即可查看更多优质内…

Pytorch nn.Linear()的基本用法与原理详解及全连接层简介

主要引用参考&#xff1a; https://blog.csdn.net/zhaohongfei_358/article/details/122797190 https://blog.csdn.net/weixin_43135178/article/details/118735850 nn.Linear的基本定义 nn.Linear定义一个神经网络的线性层&#xff0c;方法签名如下&#xff1a; torch.nn.Li…

AT32F403如何扩大SRAM

配置方法 使用雅特力的ICP 进行配置(可在官网下载) (1)当连接上芯片后,点击设备操作->选择字节 (2)选择224KB SRAM (3)然后点击应用到设备,(可以点击从设备加载,来看当前的配置) (4)打开keil5魔术棒图标 ,将Target中的IRAM1第二个选项从0x10000改为0x3800。…

虚拟电厂 能源物联新方向

今年有多热&#xff1f;据上海市气象局官微消息&#xff0c;5月29日13时09分&#xff0c;徐家汇站气温达36.1℃&#xff0c;打破了百年来的当地5月份气温*高纪录。不仅如此&#xff0c;北京、四川、江西、湖南、广东、广西等地也频频发布高温预警。 伴随着居民用电急剧攀升&am…

4.1 媒资管理模块 - Nacos与Gateway搭建

文章目录 媒资管理模块 - 媒资项目搭建一、需求分析1.1 介绍1.2 数据模型1.3 分析网关 二、 搭建Nacos2.1 服务发现中心2.2.1 Maven2.2.2 配置Nacos 2.2 配置中心2.2.1 介绍2.2.2 Maven 坐标2.2.3 配置 content-api 工程2.2.4 配置 content-service 工程2.2.5 配置 system-api …

基础算法(5):滑动窗口

1.何为滑动窗口&#xff1f; 滑动窗口其实也是一种算法&#xff0c;主要有两类&#xff1a;一类是固定窗口&#xff0c;一类是可变窗口。固定的窗口只需要一个变量记录&#xff0c;而可变窗口需要两个变量。 2.固定窗口 就像上面这个图一样。两个相邻的长度为4的红色窗口&…

HTML---CSS美化网页元素

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.div 标签&#xff1a; <div>是HTML中的一个常用标签&#xff0c;用于定义HTML文档中的一个区块&#xff08;或一个容器&#xff09;。它可以包含其他HTML元素&#xff0c;如文本、图像…

探秘 AJAX:让网页变得更智能的异步技术(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

如何编写好的测试用例?

对于软件测试工程师来说&#xff0c;设计测试用例和提交缺陷报告是最基本的职业技能。是非常重要的部分。一个好的测试用例能够指示测试人员如何对软件进行测试。在这篇文章中&#xff0c;我们将介绍测试用例设计常用的几种方法&#xff0c;以及如何编写高效的测试用例。 一、…

iPhone 17Pro/Max或升级4800万像素长焦镜头,配备自研Wi-Fi 7芯片。

iPhone 16未至&#xff0c;关于iPhone 17系列的相关消息就已经放出&#xff0c;到底是谁走漏了风声。 海通国际证券技术分析师Jeff Pu近日发布报告称&#xff0c;苹果将为2025年推出的iPhone 17ProMax配备4800万像素的长焦镜头。经调查&#xff0c;该分析师认为提升iPhone拍摄方…

如何在华为云上购买ECS及以镜像的方式部署华为云欧拉操作系统 (HCE OS)

写在前面 工作中遇到&#xff0c;简单整理博文内容为 华为云开发者认证 实验笔记https://edu.huaweicloud.com/certificationindex/developer/9bf91efb086a448ab4331a2f53a4d3a1理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在…

Nginx快速入门:Nginx应用场景、安装与部署(一)

1. Nginx简介 Nginx 是一个高性能的 HTTP 和反向代理服务器&#xff0c;也是一个非常流行的开源 Web 服务器软件。它是由俄罗斯程序员 Igor Sysoev 开发的&#xff0c;最初是为了解决在高并发场景下的C10k 问题&#xff08;即一个服务器进程只能处理 10,000 个并发连接&#x…

早期的OCR是怎么识别图片上的文字的?

现在的OCR技术融合了人工智能技术&#xff0c;通过深度学习&#xff0c;无论是识别的准确率还是效果都非常不错&#xff0c;那您知道在早期的OCR是通过什么技术来实现的吗&#xff1f;如果您不知道&#xff0c;那么&#xff0c;就让我来告诉您&#xff1a;它主要是基于字符的几…

DiffUtil + RecyclerView 在 Kotlin中的使用

很惭愧, 做了多年的Android开发还没有使用过DiffUtil这样解放双手的工具。 文章目录 1 DiffUtil 用来解决什么问题?2 DiffUtil 是什么?3 DiffUtil的使用4 参考文章 1 DiffUtil 用来解决什么问题? 先举几个实际开发中的例子帮助我们感受下: 加载内容流时,第一次加载了ABC,…

数据分析思维导图

参考&#xff1a; https://zhuanlan.zhihu.com/p/567761684?utm_id0 1、数据分析步骤地图 2、数据分析基础知识地图 3、数据分析技术知识地图 4、数据分析业务流程 5、数据分析师能力体系 6、数据分析思路体系 7、电商数据分析核心主题 8、数据科学技能书知识地图 9、数据挖掘…

文章解读与仿真程序复现思路——电力系统自动化EI\CSCD\北大核心《基于碳捕集-电转气的矿区综合能源系统协同优化调度》

这个标题涉及到碳捕集、电力转化为气体&#xff08;可能是指电力转化为氢气等&#xff09;、矿区综合能源系统以及协同优化调度等概念。让我们逐步解读&#xff1a; 碳捕集&#xff08;Carbon Capture&#xff09;&#xff1a; 这指的是通过不同技术手段捕获和隔离工业过程中产…