You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS 17下NSURL百分比双重编码问题原因咨询

iOS 17 中 NSURL 双重编码 % 的原因分析与解决方案

问题背景

iOS 17 起,NSURL 的解析规则从 RFC 1738/1808 切换为 RFC 3986。你的应用原本通过自定义编码逻辑处理 URL 宏替换后的子分隔符,但在 iOS 17 中出现了 % 被双重编码(变为 %25)的问题,比如已编码的 abc%2Fdev 被转为 abc%25%2Fdev。

双重编码的原因

这并非 Bug,是 iOS 17 严格遵循 RFC 3986 规范后的解析行为导致:

  • RFC 3986 对百分号的约束:% 仅在作为编码前缀(后跟两位十六进制字符)时才是合法的。若 URL 中出现孤立的 %,或 % 后未跟上合法十六进制字符,会被判定为无效字符,触发全局重新编码。
  • URL 中存在未处理的无效字符:你的示例里,未替换的宏 [ASSETURI] 包含 [ 和 ],这两个属于 RFC 3986 定义的通用分隔符,在 iOS 17 的 NSURL 解析中会被视为无效字符。当 URL 存在这类无效内容时,NSURL 会对整个 URL 重新编码,包括已编码好的 %2F——此时 % 被当作普通字符再次编码为 %25,最终变成 %25%2F。
  • 新旧系统行为差异:iOS 17 之前遵循的 RFC 1738/1808 对无效字符处理更宽松,不会触发全局重新编码,因此无双重编码问题。

解决方案

核心是确保传入 NSURL URLWithString: 的字符串完全符合 RFC 3986 规范:

  1. 清理未替换的宏占位符:若宏无对应值,直接从 URL 参数中移除,或替换为空字符串后再处理编码,不要保留 [ASSETURI] 这类无效格式内容。
  2. 分部分编码并构建 URL:避免直接对整个 URL 字符串编码,拆分 URL 各组成部分(协议、主机、路径、参数等)分别编码后拼接,推荐使用 NSURLComponents 自动处理编码:

示例代码:

NSURLComponents *components = [[NSURLComponents alloc] initWithString:@"http://google.com/ad/1"];
NSMutableArray<NSURLQueryItem *> *queryItems = [NSMutableArray array];

// 处理 ASSETURI 参数(有值才添加)
NSString *assetURIValue = nil; // 你的宏值
if (assetURIValue.length > 0) {
    [queryItems addObject:[[NSURLQueryItem alloc] initWithName:@"asseturl" value:assetURIValue]];
}

// 处理 PARTNER 参数
NSString *partnerValue = @"abc/dev";
[queryItems addObject:[[NSURLQueryItem alloc] initWithName:@"partner" value:partnerValue]];

components.queryItems = queryItems;
NSURL *finalURL = components.URL;

NSURLComponents 会自动按 RFC 3986 规范处理参数编码,既不会重复编码合法字符,也能正确处理各类分隔符。

内容的提问来源于stack exchange,提问作者Chen Xiaofeng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:43:22