Info.plist 默认为二进制格式,非纯文本XML;编辑需用plutil转换格式,且XML中key后必须紧跟显式类型标签(如<string>、<true/>),类型错误或结构缺失将导致解析失败、App崩溃。

plist 文件本质就是 XML(但不全是)
iOS 的 Info.plist 默认是二进制格式,不是纯文本 XML —— 这是绝大多数人误以为“改完 XML 就生效”的根源。Xcode 项目里看到的可读内容,其实是 Xcode 在编辑时自动转成 XML 格式显示;保存时可能又转回二进制,尤其当你用 Xcode 外部工具(比如 VS Code 直接改)再保存,就容易出问题。
- 用
plutil -s Info.plist可查看当前格式:输出xml1表示 XML,binary1表示二进制 - 强制转为 XML:
plutil -convert xml1 Info.plist;转回二进制:plutil -convert binary1 Info.plist - 二进制 plist 更紧凑、加载更快,系统运行时默认偏好二进制;XML 仅用于人工编辑和版本控制友好
XML 结构里 key 和 value 的类型必须显式声明
plist XML 不是自由格式的键值对,每个 <key> 后面必须紧跟一个带类型标签的 value,比如 <string>、<true/>、<integer>。漏掉类型或写错(比如把 <boolean>YES</boolean> 当作有效写法),会导致 CFPropertyListCreateFromXMLData 解析失败,App 启动直接 crash,错误日志里常出现 Could not parse property list data。
- 布尔值只能用
<true/>或<false/>,不能写<bool>1</bool>或<string>YES</string> - 数字优先用
<integer>(整数)或<real>(浮点),避免用<string>123</string>冒充数字 —— 某些 API(如CFBundleVersion校验)会严格检查类型 - 数组和字典必须用
<array>/<dict>包裹,不能靠缩进或换行暗示结构
Info.plist 中常见字段的类型陷阱
很多字段看似是字符串,实际有隐含类型约束。比如 UIBackgroundModes 是数组,但新手常写成字符串;NSLocationWhenInUseUsageDescription 看似普通字符串,但如果父级 <dict> 缺少对应 <key> 标签,整个 key 就会被忽略 —— 而且 Xcode 不报错,只静默失效。
-
CFBundleURLTypes必须是<array>,每个子项是<dict>,其中CFBundleTypeRole是<string>,CFBundleURLSchemes又得是嵌套<array>—— 少一层标签,URL Scheme 注册就失败 -
LSApplicationQueriesSchemes是字符串数组,但 iOS 9+ 要求必须声明,否则canOpenURL:返回NO,且控制台无提示 -
NSAppTransportSecurity是字典,但NSAllowsArbitraryLoads必须是<true/>或<false/>,写成<string>YES</string>会导致 ATS 配置不生效
在代码里读取 plist 时,别假设路径或编码永远可靠
用 NSDictionary(contentsOfFile:) 或 Bundle.main.path(forResource:ofType:) 加载自定义 plist 时,路径拼错、扩展名大小写不符(.PLIST ≠ .plist)、文件没加进 target 的 Copy Bundle Resources,都会让返回值为 nil —— 而且 Swift 里如果强制解包,直接 crash。
- 永远先检查路径是否存在:
Bundle.main.path(forResource: "Config", ofType: "plist") != nil - 用
NSDictionary(contentsOf:)替代contentsOfFile:,它会自动处理编码(XML plist 默认 UTF-8,但旧工具可能存为 UTF-16) - 自定义 plist 若含中文或特殊字符,确保文件保存为 UTF-8 without BOM;BOM 会导致解析失败,错误信息可能是
XML parser error: Invalid token
<true/> 标签,整个功能就哑火。











