苹果官方的文章《Entitlement问题定位指南》:
https://developer.apple.com/library/ios/technotes/tn2415/_index.html
本着“知其然,知其所以然”的精神,通读了几遍,终于对XCode管理配置文件的原理,有了稍微清晰一点的概念。以下是一些笔记:
什么是Entitlement?
Entitlement(权限),可以想象成App里用于描述该App可以调用哪些服务的字符串。苹果的操作系统(mac os或者iOS)会通过检查这个串,决定这个应用是否可以调用相关功能。比如iCloud权限,推送服务,健康服务等。
常见的Entitlement错误
- 编译打包时
|
- 安装时
|
- 提交到苹果商店时
|
- 错误的值
|
查错流程
下图是遇到Entitlement错误时,完整的检查流程:

注意: PP = Provisioning Profile 配置文件
- 在Xcode里设置目标应用的功能 (Target Capabilities)
- 苹果开发者用户中心网站的 App ID服务
- 通过网站(与2相同)创建Provisioning Profile (预配置文件)
- 网站的预配置文件库
- 检查Provisioning Profile里的权限设置
- 把Provisioning Profile安装到Xcode里
- Xcode的本地Provisioning Profile文件库
- 在Xcode里配置使用哪个Provisioning Profile文件
- 在编译日志里检查哪个Provisioning Profile被使用
- 检查打包好的应用里包含的权限
- 操作系统在安装或者启动时对App进行权限检查
第一步
Entitlement的产生,也就是一个App需要包含哪些权限,可以通过Xcode自动设置也可以自己到开发者网站上设置。
通过Xcode -> project -> Target -> Capabilities 开启或者关闭指定功能

理论上,点了"Fix Issues",Xcode会自动做以下事情:
- 更新权限需求
- 注册App ID
- 为该App ID开启或者关闭相关服务
- 创建或者更新Provisioning Profile
- 下载并安装该Provisioning Profile文件,因为后边对应用进行签名的时候需要用。
如果网络和运气都好,那么就什么事都没有了。
手动操作
但是,由于苹果网站和中国网络的问题,可能不会那么顺利。如果Xcode没法自动完成任务,那就需要手动进行相关操作:
- 创建App ID,并开启服务
有些服务会需要额外的信息,比如推送服务,需要指定证书。

- 添加Provisioning Profile

- 检查Provisiong Profile包含的服务内容

- 检查本地的Profile是否包含所需要的权限
|
- 安装Profile到Xcode
如果是从网站上下载的.mobileprovision,双击该文件将自动安装到Xcode指定的位置。
- 检查Xcode本地Provisioning Profile文件库
Xcode > Preferences > Accounts > (your account) > View Details

注意,这个是旧版的了,最新的7.3版本略有不同。其中最大的不同是,刷新按钮不见了!!取而代之的是“Download All”按钮,大概是这样子:

在Action一栏,如果这个文件不在本地,会有“Download”下载按钮,如果已经下载到本地了,就没有了。
右键点已经下载的文件,有2个选项:
1. 在Finder里显示
2. 删除 (然后就可以重新下载了)
- 在Xcode里设置Provisioning Profile文件
如果所需要的Provisioning Profile文件都已经下载到本地,可以考虑让Xcode自动选择,具体的配置方法,参考苹果的另外一个文档:https://developer.apple.com/library/mac/qa/qa1814/_index.html
配置成功后,应该是这样子:

当然,你也可以手动指定签名标识(Code Signing Identity),和Provisioning Profile。
特别值得一提的是:如果Provisioning Profile文件没问题,当你指定了一个Profile以后,Code Sigining Identity的下拉列表里会提示这个Profile所属的开发者账号。
如果没有,则说明这个文件有问题或者Xcode有问题。
(这也是我那个专业同事介绍的办法,实测非常有用。)
到这一步,都正确的话,应该就没问题了。
后边是一些额外的检查:
- 查看编译日志
编译顺利的话,日志里会提示用到哪个Profile文件:

- 检查编译出来的App是否包含正确的权限
命令行:
|
有几个细节:
a. 在对App进行签名的时候,相关的服务权限就被从Profile文件里转移到应用本身的签名里了。
b. Profile也会被内置到App里。如果打开App包查看,可以看到 embedded.mobileprovision
- 操作系统对App进行检查权限
操作系统的检查,就是基于刚刚说的两个地方:应用自身的签名,内置的Profile。当二者不一致时,就会报错。除了权限外,操作系统还会检查App ID是否一致。
- 提交到苹果商店前检查权限设置
这是整个流程的最后一个可以检查权限是否错误的地方

其他
- 手动添加Entitlement文件
通常,Xcode会自动管理Entitlement文件,所以我们并不需要在Xcode Project的Buidling Settings -> Code Signing -> Code Signing Entitlements 特意设置文件。
旧版本的Xcode,你需要自己添加Entitlement文件:

.entitlements文件的格式(应该也是.plist格式)

- Entitlement常见字段介绍
- beta-reports-active
- team-identifier
- get-task-allow
- application-identifier 应用的App ID,格式是 <prefix>.<bundle_id>
- keychain-access-groups
- push-notification
- App ID 前缀检查
操作系统还会对App ID的前缀(也就是团队id)进行检查,如果发现App签名里的前缀和profile文件里不一致,也会报错。
App ID前缀的相关参考:
- App ID前缀不一致错误: https://developer.apple.com/library/ios/qa/qa1879/_index.html
- 管理多个App ID前缀: https://developer.apple.com/library/ios/technotes/tn2311/_index.html
- 钥匙串访问警告: https://developer.apple.com/library/ios/qa/qa1726/_index.html
- 升级App时提示App ID与当前安装的App不一致:https://developer.apple.com/library/ios/technotes/tn2319/_index.html#//apple_ref/doc/uid/DTS40013778-CH1-ERRORMESSAGES-UPGRADE_S_APPLICATION_IDENTIFIER_DOES_NOT_MATCH_THE_INSTALLED_APP
















