Highlight
Apple 在 App Store Connect 中新增了 900 个价格档位、TestFlight 内部构建标记、沙盒 Family Sharing 测试、区域化预购和 Game Center API 支持,让开发者从定价、测试到上架的全流程都能更精细地控制。
核心内容
应用内购买与定价
以前做应用内购买(IAP)需要写大量 UI 代码,还要处理本地化、无障碍和不同平台的适配。开发者经常为了一套购买界面投入数天工作量。
Apple 今年推出了 StoreKit for SwiftUI。在 App Store Connect 配置好商品后,回到 Xcode 只需几行代码就能生成完整的购买界面。这个界面自动支持所有 App Store 语言和系统无障碍功能。
你可以用最简实现快速上线,也可以自定义背景、按钮和样式,让购买页与 App 风格统一。如果你在 App Store 上推广了 IAP,还能直接调用推广图标显示在购买页中。
(01:11)
定价方面,Apple 今年将价格档位从原来的选择扩展到了 900 个。开发者可以:
- 选择一个基准区域,自动换算其他区域和货币的价格
- 让 App Store 根据汇率和税率变化自动调整国际定价,或选择手动管理
- 按区域设置 IAP 和订阅的可用性
(02:09)
TestFlight 测试管理
测试人员管理一直是痛点。TestFlight 虽然能分发测试包,但开发者很难判断哪些测试者真正参与了测试、遇到了多少崩溃、提供了多少反馈。
今年 TestFlight 新增了设备列,显示测试者最近一次安装测试包的设备和系统版本。你可以按测试数据过滤,批量选择测试者进行重新邀请、添加到分组或移除。所有这些数据都可通过 App Store Connect API 获取。
(03:59)
更关键的是构建分发控制。从 Xcode 分发构建时,你可以标记某个构建为”TestFlight Internal Only”。被标记的构建不会进入外部 TestFlight,也不能提交 App Store 审核。在 App Store Connect 中,这些构建会有明确标识,避免原型代码意外外流。
(04:41)
Xcode Cloud 也加入了 TestFlight “What to Test” 的自动上传。你可以在项目同级目录放一个 TestFlight 文件夹,里面写纯文本的测试要点清单;或者写一个自定义构建脚本,从 commit message 中提取测试说明。这些信息会自动同步到 App Store Connect,分发给测试者。
(05:12)
沙盒测试增强
Family Sharing 让用户可以与家人共享订阅和 IAP,但以前沙盒环境无法测试这个功能。
今年 Apple 允许在沙盒中将测试账户组合成家庭组,最多 6 个账户。在 iOS 设备上,沙盒测试者现在可以:
- 查看家庭成员并停止共享自动续期订阅或非消耗品
- 修改订阅续费速率
- 测试中断购买流程
- 直接在设备上清除购买历史
(05:59)
产品页与隐私
xrOS 的推出带来了新的隐私数据类型。如果你的 App 收集了用户周围环境数据,需要在隐私标签中选择”Environment Scanning”;收集手部结构或动作选择”Hands”;收集头部动作选择”Head”。这些标签会出现在所有平台的 App Store 上,包括使用 ARKit 的 iOS App。
(07:34)
预购功能现在支持按区域开启。你可以先在部分区域正式上架(软启动),同时在其他区域开放预购。这通过重新设计的可用性页面来管理。
产品页优化测试(A/B 测试)也有改进:测试会一直运行到你手动停止,不再受新版本发布影响。你可以在推送更新的同时监控正在运行的测试。
(08:37)
App Store Connect API 扩展
API 今年新增了 IAP 和订阅管理、客户评论回复、沙盒测试者管理。即将推出的 Game Center API 支持:
- 创建、配置和归档排行榜与成就
- 通过 server-to-server API 提交分数和成就解锁事件
- 从排行榜移除分数和玩家,自动处理作弊行为
- 用自定义规则(如技能等级或区域)匹配玩家
API 认证也有更新。你可以生成营销和客服专用的 API key,限制其只能管理营销元数据或回复评论。还可以创建基于用户的 key,权限与你在 App Store Connect 中的角色一致。
(10:24)
详细内容
StoreKit for SwiftUI 使用方式
StoreKit for SwiftUI 的核心是两个视图:StoreView 和 SubscriptionStoreView。
import StoreKit
import SwiftUI
struct ContentView: View {
var body: some View {
// 展示所有可用的 IAP 产品
StoreView(ids: ["premium_monthly", "premium_yearly"])
// 展示订阅选项
SubscriptionStoreView(groupID: "premium_group")
}
}
关键点:
StoreView(ids:)传入产品在 App Store Connect 中配置的 ID 列表SubscriptionStoreView(groupID:)传入订阅组的 ID- 这两个视图自动处理产品加载、本地化、无障碍和购买流程
- 无需手动调用
SKProductsRequest或处理交易状态机
自定义样式示例:
SubscriptionStoreView(groupID: "premium_group") {
VStack {
Image("app_icon")
.resizable()
.frame(width: 80, height: 80)
Text("升级至高级版")
.font(.title)
}
}
.storeButton(.visible, for: .restorePurchases)
.subscriptionStoreButtonLabel(.multiline)
关键点:
- 在闭包中自定义顶部内容区域
.storeButton(.visible, for: .restorePurchases)显示恢复购买按钮.subscriptionStoreButtonLabel(.multiline)让订阅按钮显示多行信息
TestFlight “What to Test” 文件结构
在 Xcode 项目或 workspace 同级目录创建文件夹结构:
MyApp/
├── MyApp.xcodeproj
├── MyApp/
│ └── ...
└── TestFlight/
└── WhatToTest.en-US.txt
└── WhatToTest.zh-Hans.txt
关键点:
TestFlight/文件夹必须与.xcodeproj或.xcworkspace同级- 文件名格式为
WhatToTest.{locale}.txt - 支持所有 App Store 语言 locale
- Xcode Cloud 构建时会自动读取并上传到 App Store Connect
或者用构建脚本从 git log 提取:
#!/bin/bash
# 放在 Xcode Cloud 的 ci_post_xcodebuild.sh 中
COMMITS=$(git log --pretty=format:"- %s" $CI_PREVIOUS_SUCCESSFUL_COMMIT..HEAD)
echo "$COMMITS" > "$CI_ARCHIVE_PATH/WhatToTest.txt"
关键点:
ci_post_xcodebuild.sh是 Xcode Cloud 的 post-build 钩子脚本$CI_PREVIOUS_SUCCESSFUL_COMMIT是上次成功构建的 commit hash- 输出到
$CI_ARCHIVE_PATH下的WhatToTest.txt会被 Xcode Cloud 识别
App Store Connect API 新端点
Game Center API 示例(使用 JWT 认证):
# 创建排行榜
JWT_TOKEN=$(generate_jwt)
curl -X POST \
https://api.appstoreconnect.apple.com/v1/gameCenterLeaderboards \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "gameCenterLeaderboards",
"attributes": {
"referenceName": "Weekly High Score",
"vendorIdentifier": "weekly_high_score",
"defaultSortOrder": "DESCENDING",
"scoreFormatType": "INTEGER"
},
"relationships": {
"gameCenterGroup": {
"data": {
"type": "gameCenterGroups",
"id": "GROUP_ID"
}
}
}
}
}'
关键点:
- 使用 App Store Connect API 的 JWT 认证方式
referenceName是排行榜的显示名称vendorIdentifier是你在代码中引用的 IDdefaultSortOrder可以是DESCENDING或ASCENDINGscoreFormatType支持INTEGER、FLOAT等格式
server-to-server 提交分数:
curl -X POST \
https://api.appstoreconnect.apple.com/v1/gameCenterLeaderboardEntries \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "gameCenterLeaderboardEntries",
"attributes": {
"score": 15000,
"playerId": "PLAYER_ID",
"context": 1
},
"relationships": {
"gameCenterLeaderboard": {
"data": {
"type": "gameCenterLeaderboards",
"id": "LEADERBOARD_ID"
}
}
}
}
}'
关键点:
playerId是 Game Center 玩家的唯一标识context是可选的附加数据,可以用来存储关卡编号等信息- 适合跨平台游戏,在服务器端统一提交分数
核心启发
1. 用 StoreKit for SwiftUI 替代自定义购买页
- 做什么:把现有的 IAP 购买流程从手动
SKProductsRequest+ 自定义 UI 迁移到 StoreKit for SwiftUI - 为什么值得做:几行代码替代数百行 UI 和状态管理代码,自动获得本地化、无障碍和系统风格
- 怎么开始:在 App Store Connect 配置好产品,在 SwiftUI 视图中使用
StoreView或SubscriptionStoreView,逐步替换旧代码
2. 建立 TestFlight 自动化测试工作流
- 做什么:用 Xcode Cloud 自动提取 commit message 作为 “What to Test” 内容,配合 Internal Only 标记管理构建分发
- 为什么值得做:测试者每次收到构建时都能看到本次变更要点,内部原型不会意外外流
- 怎么开始:在项目中添加
TestFlight/WhatToTest.en-US.txt,配置 Xcode Cloud 的ci_post_xcodebuild.sh脚本提取 git log
3. 用沙盒 Family Sharing 测试订阅共享
- 做什么:在 App Store Connect 中创建 2-6 个沙盒测试账户组成家庭组,测试订阅共享的完整流程
- 为什么值得做:Family Sharing 是订阅类 App 的重要转化渠道,以前无法测试,现在可以在发布前验证
- 怎么开始:在 App Store Connect > Users and Access > Sandbox Testers 中创建账户并配置家庭组,在设备上登录不同账户测试
4. 用 Game Center API 实现跨平台排行榜
- 做什么:通过 server-to-server API 从游戏后端服务器提交分数和成就
- 为什么值得做:跨平台游戏(如同时有 iOS 和 Web 版本)可以在服务器端统一管理 Game Center 数据
- 怎么开始:在 App Store Connect 中生成 API key,用 JWT 认证调用 Game Center 端点创建排行榜,在游戏服务器中集成分数提交逻辑
5. 按区域分阶段发布
- 做什么:先在核心市场正式上架收集反馈,同时在其他市场开放预购
- 为什么值得做:降低全球同步发布的风险,用真实用户数据优化产品后再扩展市场
- 怎么开始:在 App Store Connect 的可用性页面中,选择部分区域设为”可下载”,其他区域设为”预购”
关联 Session
- What’s new in App Store pricing — 深入了解定价更新和 App Store Connect API 定价端点
- Meet StoreKit for SwiftUI — 用几行代码实现应用内购买和订阅界面
- Simplify distribution in Xcode and Xcode Cloud — 简化 Xcode 和 Xcode Cloud 的分发流程
- Explore testing in-app purchases — StoreKit 测试、沙盒测试和 TestFlight 测试
- What’s new in privacy — 隐私功能更新和第三方 SDK 新特性
评论
GitHub Issues · utterances