之前遇到的问题是,打包完成以后发现,没有打包推送证书,然后重新打包并上传到app store ,但是最后发现还是没有推送功能。
后来分析了一下原因是,app 后台appid设置地方没有打开推送功能,然后再打开依然不能推送,原因是此时现场的ipa包的Provisioning Profile文件还是老的,而Provisioning Profile里面设置了该app 是否有推送功能,最简单的最好的办法是重新生成Provisioning Profile文件并打包,不需要重新生成推送证书。
当你接触iOS开发,一般都会涉及到Provisioning Profile(配置文件)。大多数时候是通过苹果的“Development Provisioning Assistant”,将配置文件安装到正确的地方,并使用Keychain Access(钥匙串访问程序)获取证书和密钥,并将其安装到钥匙串中。一段时间过后,你可能会遇到如下问题:
Code Sign error(代码签名错误):
The executable was signed with invalid entitlements.(使用了无效的证书对程序进行了签名)
Valid signing identity not found.(没有找到有效的签名标示)
No unexpired provisioning profiles found that contain any of the keychain’s signing certificates(在钥匙串的签名证书中,没有发现期望的配置文件)
遇到上面的问题后,你可能通过google,在Stack Overflow上找到一些类似的问题,并成功把问题解决掉,然后接着做别的任务。我见过解决上面问题的方法是“删除所有的配置文件,并重头开始”。一般这是可以解决问题的,不过本系列文章的目标是让你不用删除所有的配置文件从头开始,就可以解决上面的问题。
开始吧
每个配置文件实际上都是一个用PKCS#7签名后的plist文件。PKCS一组公钥密码学标准。PKCS#7是加密消息语法的标准。苹果使用这个标准对plist文件进行签名,通过签名,OS(操作系统)可以验证被安装的程序是来自合法的开发者(通过验证可以知道plist文件中的内容有没有被修改过)。plist文件中的最后一部分是非常重要的,稍后你将知道为什么。
在Terminal(终端程序)中使用vi打开一个配置文件,可以看到类似如下的内容:
0<82>^^è^F *<86>H<86>÷^M^A^G^B <82>^^Ù0<82>^^Õ^B^A^A1^K0 ^F^E+^N^C^B^Z^E^@0<82>^N®^F *<86>H<86>÷^M^A^G^A <82>^N<9f>^D<82>^N<9b><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
上面这部分内容是PKCS#7签名的头部。往下看到的许多内容才是真正的签名:
</dict>
</plist>
<82>^M²0<82>^Cù0<82>^Bá ^C^B^A^B^B^A^_0^M^F *<86>H<86>÷^M^A^A^E^E^@0y1^K0 ^F^CU^D^F^S^BUS1^S0^Q^F^CU^D
^S
Apple Inc.1&0$^F^CU^D^K^S^]Apple Certification Authority1-0+^F^CU^D^C^S$Apple iPhone Certification Authority0^^^W^M080521020415Z^W^M200521020415Z0Y1^K0 ^F^CU^D^F^S^BUS1^S0^Q^F^CU^D
^S
Apple Inc.1503^F^CU^D^C^S,Apple iPhone OS Provisioning Profile Signing0<82>^A"0^M^F *<86>H<86>÷^M^A^A^A^E^@^C<82>^A^O^@0<82>^A
注意观察上面内容的底部,可以看到类似这样的字符串:Apple Inc., Apple Certification Authority 和 Apple iPhone OS Provisioning Profile Signing,通过这些内容可以知道这个文件进行了数字签名。配置文件是通过iOS Provisioning Portal创建的。当你选择了App ID,以及适当数量的设备UDIDs和Entitlement之后,苹果会将所有的这些信息数字签名到配置文件(Provisioning Profile)中,这样iOS就可以验证配置文件是否真的由苹果分发。
当这个配置文件被数字签名之后,你可能会问“我如何验证这个签名?”,在Terminal程序中,你可以使用openssl程序进行验证。Openssl不仅可以验证签名,还可以将签名信息打印出来,在Terminal程序中输入如下内容就可以进行验证:
openssl smime -in /path/to/your.mobileprovision -inform der -verify
现在,如果你希望手动编辑一下配置文件。比如你想把苹果新设备的UDID添加到配置文件中(不通过Provisioning Portal)。编辑之后,验证会失败,并得到如下类似的信息:
openssl smime -in Key_Grinder_Beta_Dev.mobileprovision -inform der -verify
Error reading S/MIME message
10163:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:/SourceCache/OpenSSL098/OpenSSL098-47/src/crypto/asn1/tasn_dec.c:1315:
10163:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:/SourceCache/OpenSSL098/OpenSSL098-47/src/crypto/asn1/tasn_dec.c:657:Field=signer_info, Type=PKCS7_SIGNED
10163:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:/SourceCache/OpenSSL098/OpenSSL098-47/src/crypto/asn1/tasn_dec.c:747:
10163:error:0D08403A:asn1 encoding routines:ASN1_TEMPLATE_EX_D2I:nested asn1 error:/SourceCache/OpenSSL098/OpenSSL098-47/src/crypto/asn1/tasn_dec.c:577:Field=d.sign,Type=PKCS7
这还不是我见过最好的错误(苹果限制了每个开发者账号只能最多使用100台设备,并防止你添加更多的UDIDs)
之前提到过Provisioning Profile实际上就是一个plist文件。下面我们从头开始看看这个plist文件中的键/值。这里有一个Provisioning Profile.plist示例文件,在阅读下面的内容时,可以参考:
1.在plist字典中的第一项是“AppIDName.” 这是你在 iOS Provisioning Portal中给App ID指定的名字。
2.下一项是“ApplicationIdentifierPrefix.” 这是在创建App ID时,由provisioning protal生成的10个字符。在 iOS Provisioning Portal中称为Bundle Seed ID(App ID前缀)。
3.下一项“CreationDate” 是一个日期时间戳,表示这个Provisioning Profile文件被创建的时间。
4.接下来的“DeveloperCertificates”之所以很有趣是有原因的。首先,它是一个数组(array),所以这里面可以包含多个证书。不过在这里我只看到一个证书。其次,它是base64编码的开发者证书。你可以将<data>标签中的文本拷贝并粘贴到另外一个文件中(粘贴在“—–BEGIN CERTIFICATE—–”和 “—–END CERTIFICATE—–”之间)。
看起来是这样的:
1.-----BEGIN CERTIFICATE-----
2.MIIFnTCCBIWgAwIBAgIIDlfxd9Mb0+gwDQYJKoZIhvcNAQEFBQAwgZYxCzAJ
3.BgNVBAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBs
4.ZSBXb3JsZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBw
5.bGUgV29ybGR3aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlv
6.biBBdXRob3JpdHkwHhcNMTIwODAzMjEzNDQxWhcNMTMwODAzMjEzNDQxWjCB
7.kDEaMBgGCgmSJomT8ixkAQEMClc1OFo3OVc4WDkxMjAwBgNVBAMMKWlQaG9u
8.ZSBEZXZlbG9wZXI6IEpheSBHcmF2ZXMgKEU2TDg3NlFGTTYpMRMwEQYDVQQL
9.DAo5SzlGOUxDVjc0MRwwGgYDVQQKDBNNYXNzaXZlbHkgT3ZlcnJhdGVkMQsw
10.CQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANdD
11.4hK9TjfXqoe1p0WpxvEULd575mhDpaKkvuUPG29bFEDIQrf2h0DTIGbvu6rR
12.z09+nxI0JkN56A0JO2OygfJGG5hcKm78CRtNFrDrOksOKD12PJkubnxhAi4y
13.sMI9M5+WCE+zV48VwMMI7dHLG7Pg5irMaqecnqNpRCoKxMeeziki+fD3H7jU
14.MiC6CA7iKCVHoDZKycF9Q3CeA5+sGWO28IqDYbOiCdeFhaiLYVVZJlmdKjqU
15.gHBsQWjj/vCeyikf+Ls52pPrD9+e0VgBnzrK2RcDPdNZON9gVAp1GeNNsmte
16.gmHGMlEzpLXF3/4RxOr2eLQ5iy5W/2SBUWpdSRUCAwEAAaOCAfEwggHtMB0G
17.A1UdDgQWBBSQHWHglRuqJq0gR4KzILT29p9ZIDAMBgNVHRMBAf8EAjAAMB8G
18.A1UdIwQYMBaAFIgnFwmpthhgi+zruvZHWcVSVKO3MIIBDwYDVR0gBIIBBjCC
19.AQIwgf8GCSqGSIb3Y2QFATCB8TCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5j
20.ZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFj
21.Y2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJt
22.cyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBh
23.bmQgY2VydGlmaWNhdGlvbiBwcmFjdGljZSBzdGF0ZW1lbnRzLjApBggrBgEF
24.BQcCARYdaHR0cDovL3d3dy5hcHBsZS5jb20vYXBwbGVjYS8wTQYDVR0fBEYw
25.RDBCoECgPoY8aHR0cDovL2RldmVsb3Blci5hcHBsZS5jb20vY2VydGlmaWNh
26.dGlvbmF1dGhvcml0eS93d2RyY2EuY3JsMA4GA1UdDwEB/wQEAwIHgDAWBgNV
27.HSUBAf8EDDAKBggrBgEFBQcDAzATBgoqhkiG92NkBgECAQH/BAIFADANBgkq
28.hkiG9w0BAQUFAAOCAQEAApeWS6BrVv0jOFY7F0kCUR5h/RrXaMnUwjyFsF6r
29.HilDf70nvgIgIohtK2Uez5lkYavyDBzQGsN6gHbGLvg+4camDfT28quRPumk
30.qcIwZBCyB5A11HGlrer0Jz6iev6NAX5SSODWbAuzXJBs72EKuwF/+pGB5x1n
31.2YsKuQd8nQ+vD7kIHenP4n7goY8RSv8QQ8DhIkkgXqSbnZ6Xp4DKSTWgzb0T
32.a28g57YJlFjYioqkVFDi+5BANXxL0lHNeLAPXIY+TqQ/MWho/F6L2ONZyNT6
33.K6cadeQuTDgimoiTIjUGnAAR33SW7rIfHJNr2tNEtKu/aerKYCfWDLHf0QK9
34.1g==
35.-----END CERTIFICATE-----
然后在终端程序中使用命令 openssl x509 -text -in MassivelyOverrated.pem,就可以看到证书的所有信息,如下所示:
1.Certificate:
2. Data:
3. Version: 3 (0x2)
4. Serial Number:
5. 0e:57:f1:77:d3:1b:d3:e8
6. Signature Algorithm: sha1WithRSAEncryption
7. Issuer: C=US, O=Apple Inc., OU=Apple Worldwide Developer Relations, CN=Apple Worldwide Developer Relations Certification Authority
8. Validity
9. Not Before: Aug 3 21:34:41 2012 GMT
10. Not After : Aug 3 21:34:41 2013 GMT
11. Subject: UID=W58Z79W8X9, CN=iPhone Developer: Jay Graves (E6L876QFM6), OU=9K9F9LCV74, O=Massively Overrated, C=US
12. Subject Public Key Info:
13. Public Key Algorithm: rsaEncryption
14. RSA Public Key: (2048 bit)
15. Modulus (2048 bit):
16. 00:d7:43:e2:12:bd:4e:37:d7:aa:87:b5:a7:45:a9:
17. c6:f1:14:2d:de:7b:e6:68:43:a5:a2:a4:be:e5:0f:
18. 1b:6f:5b:14:40:c8:42:b7:f6:87:40:d3:20:66:ef:
19. bb:aa:d1:cf:4f:7e:9f:12:34:26:43:79:e8:0d:09:
20. 3b:63:b2:81:f2:46:1b:98:5c:2a:6e:fc:09:1b:4d:
21. 16:b0:eb:3a:4b:0e:28:3d:76:3c:99:2e:6e:7c:61:
22. 02:2e:32:b0:c2:3d:33:9f:96:08:4f:b3:57:8f:15:
23. c0:c3:08:ed:d1:cb:1b:b3:e0:e6:2a:cc:6a:a7:9c:
24. 9e:a3:69:44:2a:0a:c4:c7:9e:ce:29:22:f9:f0:f7:
25. 1f:b8:d4:32:20:ba:08:0e:e2:28:25:47:a0:36:4a:
26. c9:c1:7d:43:70:9e:03:9f:ac:19:63:b6:f0:8a:83:
27. 61:b3:a2:09:d7:85:85:a8:8b:61:55:59:26:59:9d:
28. 2a:3a:94:80:70:6c:41:68:e3:fe:f0:9e:ca:29:1f:
29. f8:bb:39:da:93:eb:0f:df:9e:d1:58:01:9f:3a:ca:
30. d9:17:03:3d:d3:59:38:df:60:54:0a:75:19:e3:4d:
31. b2:6b:5e:82:61:c6:32:51:33:a4:b5:c5:df:fe:11:
32. c4:ea:f6:78:b4:39:8b:2e:56:ff:64:81:51:6a:5d:
33. 49:15
34. Exponent: 65537 (0x10001)
35. X509v3 extensions:
36. X509v3 Subject Key Identifier:
37. 90:1D:61:E0:95:1B:AA:26:AD:20:47:82:B3:20:B4:F6:F6:9F:59:20
38. X509v3 Basic Constraints: critical
39. CA:FALSE
40. X509v3 Authority Key Identifier:
41. keyid:88:27:17:09:A9:B6:18:60:8B:EC:EB:BA:F6:47:59:C5:52:54:A3:B7
42.
43. X509v3 Certificate Policies:
44. Policy: 1.2.840.113635.100.5.1
45. User Notice:
46. Explicit Text: Reliance on this certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certificate policy and certification practice statements.
47. CPS: http://www.apple.com/appleca/
48.
49. X509v3 CRL Distribution Points:
50. URI:http://developer.apple.com/certificationauthority/wwdrca.crl
51.
52. X509v3 Key Usage: critical
53. Digital Signature
54. X509v3 Extended Key Usage: critical
55. Code Signing
56. 1.2.840.113635.100.6.1.2: critical
57. ..
58. Signature Algorithm: sha1WithRSAEncryption
59. 02:97:96:4b:a0:6b:56:fd:23:38:56:3b:17:49:02:51:1e:61:
60. fd:1a:d7:68:c9:d4:c2:3c:85:b0:5e:ab:1e:29:43:7f:bd:27:
61. be:02:20:22:88:6d:2b:65:1e:cf:99:64:61:ab:f2:0c:1c:d0:
62. 1a:c3:7a:80:76:c6:2e:f8:3e:e1:c6:a6:0d:f4:f6:f2:ab:91:
63. 3e:e9:a4:a9:c2:30:64:10:b2:07:90:35:d4:71:a5:ad:ea:f4:
64. 27:3e:a2:7a:fe:8d:01:7e:52:48:e0:d6:6c:0b:b3:5c:90:6c:
65. ef:61:0a:bb:01:7f:fa:91:81:e7:1d:67:d9:8b:0a:b9:07:7c:
66. 9d:0f:af:0f:b9:08:1d:e9:cf:e2:7e:e0:a1:8f:11:4a:ff:10:
67. 43:c0:e1:22:49:20:5e:a4:9b:9d:9e:97:a7:80:ca:49:35:a0:
68. cd:bd:13:6b:6f:20:e7:b6:09:94:58:d8:8a:8a:a4:54:50:e2:
69. fb:90:40:35:7c:4b:d2:51:cd:78:b0:0f:5c:86:3e:4e:a4:3f:
70. 31:68:68:fc:5e:8b:d8:e3:59:c8:d4:fa:2b:a7:1a:75:e4:2e:
71. 4c:38:22:9a:88:93:22:35:06:9c:00:11:df:74:96:ee:b2:1f:
72. 1c:93:6b:da:d3:44:b4:ab:bf:69:ea:ca:60:27:d6:0c:b1:df:
73. d1:02:bd:d6
74.-----BEGIN CERTIFICATE-----
75.MIIFnTCCBIWgAwIBAgIIDlfxd9Mb0+gwDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNV
76.BAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js
77.ZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3
78.aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
79.HhcNMTIwODAzMjEzNDQxWhcNMTMwODAzMjEzNDQxWjCBkDEaMBgGCgmSJomT8ixk
80.AQEMClc1OFo3OVc4WDkxMjAwBgNVBAMMKWlQaG9uZSBEZXZlbG9wZXI6IEpheSBH
81.cmF2ZXMgKEU2TDg3NlFGTTYpMRMwEQYDVQQLDAo5SzlGOUxDVjc0MRwwGgYDVQQK
82.DBNNYXNzaXZlbHkgT3ZlcnJhdGVkMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcN
83.AQEBBQADggEPADCCAQoCggEBANdD4hK9TjfXqoe1p0WpxvEULd575mhDpaKkvuUP
84.G29bFEDIQrf2h0DTIGbvu6rRz09+nxI0JkN56A0JO2OygfJGG5hcKm78CRtNFrDr
85.OksOKD12PJkubnxhAi4ysMI9M5+WCE+zV48VwMMI7dHLG7Pg5irMaqecnqNpRCoK
86.xMeeziki+fD3H7jUMiC6CA7iKCVHoDZKycF9Q3CeA5+sGWO28IqDYbOiCdeFhaiL
87.YVVZJlmdKjqUgHBsQWjj/vCeyikf+Ls52pPrD9+e0VgBnzrK2RcDPdNZON9gVAp1
88.GeNNsmtegmHGMlEzpLXF3/4RxOr2eLQ5iy5W/2SBUWpdSRUCAwEAAaOCAfEwggHt
89.MB0GA1UdDgQWBBSQHWHglRuqJq0gR4KzILT29p9ZIDAMBgNVHRMBAf8EAjAAMB8G
90.A1UdIwQYMBaAFIgnFwmpthhgi+zruvZHWcVSVKO3MIIBDwYDVR0gBIIBBjCCAQIw
91.gf8GCSqGSIb3Y2QFATCB8TCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0
92.aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ug
93.b2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0
94.aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlv
95.biBwcmFjdGljZSBzdGF0ZW1lbnRzLjApBggrBgEFBQcCARYdaHR0cDovL3d3dy5h
96.cHBsZS5jb20vYXBwbGVjYS8wTQYDVR0fBEYwRDBCoECgPoY8aHR0cDovL2RldmVs
97.b3Blci5hcHBsZS5jb20vY2VydGlmaWNhdGlvbmF1dGhvcml0eS93d2RyY2EuY3Js
98.MA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAzATBgoqhkiG
99.92NkBgECAQH/BAIFADANBgkqhkiG9w0BAQUFAAOCAQEAApeWS6BrVv0jOFY7F0kC
100.UR5h/RrXaMnUwjyFsF6rHilDf70nvgIgIohtK2Uez5lkYavyDBzQGsN6gHbGLvg+
101.4camDfT28quRPumkqcIwZBCyB5A11HGlrer0Jz6iev6NAX5SSODWbAuzXJBs72EK
102.uwF/+pGB5x1n2YsKuQd8nQ+vD7kIHenP4n7goY8RSv8QQ8DhIkkgXqSbnZ6Xp4DK
103.STWgzb0Ta28g57YJlFjYioqkVFDi+5BANXxL0lHNeLAPXIY+TqQ/MWho/F6L2ONZ
104.yNT6K6cadeQuTDgimoiTIjUGnAAR33SW7rIfHJNr2tNEtKu/aerKYCfWDLHf0QK9
105.1g==
106.-----END CERTIFICATE-----
苹果和iOS使用这个证书来验证有开发者签过名的代码。
5.下一个是“Entitlements”这里面有一个字典,字典中有许多键值对,都是与iCloud、Game Center、推送通知和调试程序相关的一些内容。这里并不打算介绍这些相关的键值内容。如果你以前遇到这样的错误“The executable was signed with invalid entitlements”,可以将这个Entitlements字典拷贝并粘贴到程序的Entitlements.plist文件中,确保程序和Provisioning的entitlements都是精确匹配的。
6.“ExpirationDate”是这个Provisioning Profile文件的过期日期。
7.“Name”是在iOS Developer Portal给这个Provisioning Profile指定的名字。
8.“ProvisionedDevices”是一个数组,里面是一个设备UDID列表,这表示了利用这个Provisioning Profile签名的程序只能安装在这里列出来的UDID设备中(我是这样认为的)。一般我打开一个Provisioning Profile文件,都是看看某个设备的UDID是否已经包含在这个数组中了。
9.“TeamIdentifier”也包含一个数组,不过我只在这个数组中看到过一个值。这个值相当于一个标示符,用来唯一标识这个Provisioning Profile文件属于哪个团队。
10. “TeamName”表示这个Provisioning Profile文件属于团队的名称。有趣的是“TeamIdentifier”是数组,但是这里的 “TeamName”不是。
11. “TimeToLive”是这个Provisioning Profile文件的有效天数。苹果将这个值设置为365天。
12. “UUID”这个值可以在Xcode工程文件中找到。每更新一次Provisioning Profile文件,这个UUID都会改变。如果你曾在Xcode中选择了某个特定的 Code Signing Identity,而不是 “iPhone Developer” 或“iPhone Distribution”,这个UUID可以在Xcode project.pbxproj文件中的“PROVISIONING_PROFILE”字段进行设置。在你将Xcode中的Provison Profile文件修改为另外一个,SCM会差分出如下结果:
1.- PROVISIONING_PROFILE = "D8F8CD60-CD85-4FEA-BF87-CD5D67FDC3EA";
2.+ PROVISIONING_PROFILE = "9B44F36C-328F-45C0-BC62-4A272CB9DAD7";
13.“Version”是这个文件数据格式的版本。苹果将其设置为1。
上面提到过,当我检查这个Provision Profile文件时,90%次都是检查 “ProvisionedDevices”数组。另外10%次是检查 “Entitlements” 和“UUID”。如果程序中使用了APNS(Apple’s Push Notification service),那么“Entitlements”这个字段将保存着apns的相关信息。这个值可以包含 “production” 或“development”的信息,也可以没有设置相关信息,不过这样的话在程序中就不能正常使用推送通知。一般在将程序提交到iTunes Connect时,我都会检查一下这个字段。
一般在Xcode中,我都是使用“UUID”来指定一个特定的Provisioning Profile文件,这样可以不依赖于Xcode的自动选择(经常会出问题)。Jenkins利用.xcconfig文件来覆盖“UUID”,可以让自动build更加容易。相信不久,你能看到相关文章。