iOS 开发指南(Flutter 开发者视角)
面向 Flutter / Android 开发者的 iOS 打包、签名、上架核心知识。iOS 的签名体系远比 Android 复杂,理解其中的概念关系是解决 99% 打包问题的关键。
与 Android 的核心对比:
| iOS | Android | |
|---|---|---|
| 签名工具 | Xcode / Keychain | keytool / jarsigner |
| 签名文件 | Certificate + Provisioning Profile | .keystore 文件 |
| 发布渠道 | App Store / TestFlight | Google Play / 第三方 |
| 测试分发 | TestFlight(最多 10,000 人) | 直接安装 APK |
| 应用 ID | Bundle ID | Application ID |
| 开发者账号费用 | $99/年(个人/公司) | $25 一次性 |
| 审核周期 | 1-3 天 | 数小时至 1 天 |
核心概念
iOS 签名涉及三个相互绑定的概念,缺一不可:
Apple Developer Account
└── Certificate(证书) # 证明"你是谁"
└── App ID / Bundle ID # 证明"这是什么应用"
└── Device(设备 UDID) # 证明"装在哪台设备上"
└── Provisioning Profile # 将以上三者绑定在一起
Certificate(证书)
证书证明代码由你签署,存储在 Mac 的 Keychain 中,包含公钥和私钥。
| 类型 | 用途 |
|---|---|
| Apple Development | 开发调试,安装到开发设备 |
| Apple Distribution | 提交 App Store / TestFlight |
证书与 Mac 机器绑定,换电脑需要导出
.p12文件迁移。
Provisioning Profile(描述文件)
描述文件是一个 .mobileprovision 文件,将 证书 + Bundle ID + 设备 打包绑定,安装到设备时系统验证此文件。
| 类型 | 用途 | 设备限制 |
|---|---|---|
| Development | 真机调试 | 最多 100 台注册设备 |
| Ad Hoc | 测试分发 | 最多 100 台注册设备 |
| App Store | 上架 / TestFlight | 无限制 |
Bundle ID
iOS 的应用唯一标识,对应 Android 的 applicationId。
com.yourcompany.yourapp
在 Flutter 项目中位于:ios/Runner.xcodeproj → General → Bundle Identifier
Apple Developer 账号
账号类型
| 类型 | 费用 | 适用场景 |
|---|---|---|
| 个人(Individual) | $99/年 | 个人开发者 |
| 公司(Organization) | $99/年 | 需要 D-U-N-S 编号 |
| 企业(Enterprise) | $299/年 | 内部分发,不能上 App Store |
注册地址:developer.apple.com
团队角色
| 角色 | 权限 |
|---|---|
| Account Holder | 全部权限,唯一 |
| Admin | 管理证书、设备、描述文件 |
| Developer | 创建开发证书,有限权限 |
证书管理
创建证书
方式一:Xcode 自动管理(推荐新手)
Xcode → Preferences → Accounts → 选择团队 → Manage Certificates → 点击 +
方式二:手动创建
- 打开 Keychain Access → 证书助手 → 从证书颁发机构请求证书
- 填写邮件,选择"存储到磁盘",生成
.certSigningRequest文件 - 上传到 developer.apple.com → Certificates → 创建证书
导出证书(换电脑 / CI 使用)
# Keychain Access 中右键证书 → 导出 → 保存为 .p12
# 设置密码,妥善保管
在 CI/CD 中使用 Base64 编码存储:
base64 -i certificate.p12 | pbcopy # 复制到剪贴板
Provisioning Profile 管理
自动管理(Automatic Signing)
Xcode 勾选 Automatically manage signing 后会自动创建和更新描述文件,适合大多数场景。
Flutter 项目配置:
# 用 Xcode 打开 iOS 项目
open ios/Runner.xcworkspace
Signing & Capabilities → 勾选 Automatically manage signing → 选择 Team
手动管理(Manual Signing)
适用于 CI/CD 或需要精确控制的场景。
- 在 developer.apple.com → Profiles → 创建描述文件
- 选择类型(App Store / Ad Hoc / Development)
- 绑定 Bundle ID、证书、设备
- 下载
.mobileprovision文件,双击安装到 Xcode
Flutter 项目 iOS 配置
关键文件
ios/
├── Runner.xcworkspace # 用这个打开,不要用 .xcodeproj
├── Runner.xcodeproj/
│ └── project.pbxproj # 签名配置存储在这里
├── Runner/
│ ├── Info.plist # 应用权限声明
│ └── GoogleService-Info.plist # Firebase 配置(如果有)
└── Podfile # CocoaPods 依赖
Info.plist 常用权限
<!-- 相机 -->
<key>NSCameraUsageDescription</key>
<string>需要访问相机以拍摄照片</string>
<!-- 相册 -->
<key>NSPhotoLibraryUsageDescription</key>
<string>需要访问相册以选择图片</string>
<!-- 位置 -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>需要获取位置以提供导航服务</string>
<!-- 麦克风 -->
<key>NSMicrophoneUsageDescription</key>
<string>需要访问麦克风以录制音频</string>
Flutter 插件通常会在 README 中说明需要添加哪些权限。
最低系统版本
# ios/Podfile
platform :ios, '13.0'
# Xcode → Runner → General → Minimum Deployments
iOS 13.0
打包(Archive)
命令行打包(推荐用于 CI)
# 1. 构建 Flutter
flutter build ios --release
# 2. 用 xcodebuild 打包(自动签名)
xcodebuild -workspace ios/Runner.xcworkspace \
-scheme Runner \
-configuration Release \
-archivePath build/Runner.xcarchive \
archive
# 3. 导出 IPA(App Store)
xcodebuild -exportArchive \
-archivePath build/Runner.xcarchive \
-exportPath build/Runner.ipa \
-exportOptionsPlist ios/ExportOptions.plist
ExportOptions.plist
<?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>
<key>method</key>
<string>app-store</string> <!-- app-store | ad-hoc | development -->
<key>teamID</key>
<string>XXXXXXXXXX</string> <!-- 10位 Team ID,在 developer.apple.com 查看 -->
<key>uploadSymbols</key>
<true/>
<key>compileBitcode</key>
<false/>
</dict>
</plist>
Xcode 图形界面打包
- Xcode → Product → Archive
- 等待构建完成,Organizer 窗口自动打开
- Distribute App → App Store Connect → Upload
TestFlight 分发
TestFlight 是 Apple 官方的测试分发平台,上传方式与正式版完全相同。
内部测试 vs 外部测试
| 内部测试 | 外部测试 | |
|---|---|---|
| 人数 | 最多 100 人 | 最多 10,000 人 |
| 资格 | 团队成员(需 Apple ID 加入团队) | 任何人(邮件邀请) |
| 审核 | 无需审核 | 需 Beta App Review |
| 有效期 | 90 天 | 90 天 |
上传 IPA
方式一:Transporter(Mac App)
下载 Transporter → 拖入 .ipa → 上传
方式二:命令行
xcrun altool --upload-app \
--type ios \
--file build/Runner.ipa/Runner.ipa \
--apiKey YOUR_API_KEY \
--apiIssuer YOUR_ISSUER_ID
方式三:Xcode Organizer
Archive 后 → Distribute App → App Store Connect → Upload
App Store 上架流程
1. App Store Connect 配置
- 新建 App → 填写 Bundle ID、SKU、名称
- 填写截图(iPhone 6.5"、iPad 12.9" 必填)
- 填写描述、关键词、隐私政策 URL
- 选择分级、类别
2. 截图尺寸要求
| 设备 | 尺寸 | 必填 |
|---|---|---|
| iPhone 6.7"(15 Pro Max) | 1290 × 2796 | 推荐 |
| iPhone 6.5"(14 Plus) | 1242 × 2688 | 必填 |
| iPhone 5.5"(8 Plus) | 1242 × 2208 | 可选 |
| iPad Pro 12.9" | 2048 × 2732 | 必填(如支持 iPad) |
3. 提交审核
App Store Connect → 选择构建版本 → 填写审核信息 → 提交审核
审核要点: - 所有请求的权限必须实际使用 - 不能包含私有 API - 应用功能需完整,无占位内容 - 内购项目需正确配置
4. 版本号规范
Flutter 的 pubspec.yaml:
version: 1.2.3+45
# └─┬─┘ └┤
# CFBundleShortVersionString (App Store 显示的版本)
# CFBundleVersion (构建号,每次上传必须递增)
CI/CD 签名方案
Fastlane Match(推荐团队使用)
Match 将证书和描述文件加密存储在 Git 仓库,团队成员和 CI 共享同一套签名文件。
gem install fastlane
fastlane match init # 初始化,填写 Git 仓库地址
fastlane match appstore # 同步 App Store 证书
fastlane match development # 同步开发证书
Matchfile:
git_url("https://github.com/yourorg/certificates")
app_identifier("com.yourcompany.yourapp")
username("your@email.com")
GitHub Actions 完整示例
- name: Install certificates
env:
P12_BASE64: ${{ secrets.IOS_P12_BASE64 }}
P12_PASSWORD: ${{ secrets.IOS_P12_PASSWORD }}
PROVISION_BASE64: ${{ secrets.IOS_PROVISION_BASE64 }}
run: |
# 创建临时 Keychain
security create-keychain -p "" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "" build.keychain
# 导入证书
echo $P12_BASE64 | base64 --decode > certificate.p12
security import certificate.p12 -k build.keychain \
-P $P12_PASSWORD -T /usr/bin/codesign
# 安装描述文件
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
echo $PROVISION_BASE64 | base64 --decode \
> ~/Library/MobileDevice/Provisioning\ Profiles/profile.mobileprovision
常见问题
No signing certificate found
No signing certificate "iOS Distribution" found
原因:当前 Mac 没有对应证书,或证书已过期。
解决:Xcode → Preferences → Accounts → Manage Certificates → 重新创建
Provisioning profile doesn't include signing certificate
原因:描述文件绑定的证书与当前证书不匹配。
解决:重新生成描述文件,或在 developer.apple.com 将当前证书加入描述文件。
The app bundle is invalid(上传时)
常见原因:
- CFBundleVersion(构建号)未递增
- 包含模拟器架构(arm64 与 x86_64 混合)
# 检查 IPA 架构
lipo -info Payload/Runner.app/Runner
Pod install 失败
cd ios
rm -rf Pods Podfile.lock
pod install --repo-update
Flutter 版本升级后签名失效
flutter clean
cd ios && pod install
重新用 Xcode 打开,检查 Signing & Capabilities 配置是否还在。