⚠️ 我们在Roadmap中用于让用户投票的countAPI已经停机六周左右。他们正在调查此事,但目前Roadmap不幸无法正常工作。countapi的提供商已告知我们,他们预计短期内无法修复API,因此我们正在寻找替代方案。
看看这个PR,我们可能很快会将其作为默认选项引入! https://github.com/AvdLee/Roadmap/pull/71
这里有一个使用Vapor(Swift)搭建自己服务器的分步指南: https://github.com/valentin-mille/RoadmapBackend
Roadmap
在您的应用内发布路线图,让用户为即将推出的功能投票,无需创建后端!
示例
设置Roadmap
创建Roadmap JSON
Roadmap使用远程JSON配置列出所有功能及其状态。我们建议将其托管在GitHub Pages或simplejsoncms.com上。
示例JSON如下:
[
{
"id": "1",
"title": "合并句子",
"status": "计划中",
"description" : "您可以在这里添加一些额外的上下文。"
},
{
"id": "2",
"title": "支持使用Finder打开",
"status": "计划中"
},
{
"id": "3",
"title": "初始发布",
"status": "已完成",
"description" : "向公众发布v1版本。",
"isFinished": true
}
]
id
和title
键是必需的,且都必须是字符串。您可以为status
或description
使用任何值。
支持本地化
如果您需要支持本地化,则需要在JSON中添加额外的可选参数localizedTitle
、localizedDescription
和localizedStatus
,如:
[
{
"id": "0",
"title": "添加地图",
"localizedTitle": [
{
"language": "ar",
"value": "اضافة خارطة"
},
{
"language": "en",
"value": "Adding a map"
}
],
"status": "计划中",
"localizedStatus": [
{
"language": "ar",
"value": "مجدولة"
},
{
"language": "en",
"value": "Planned"
}
],
"description": "一些描述",
"localizedDescription": [
{
"language": "ar",
"value": "اضافة خارطة لمعرفة الاماكن القريبة"
},
{
"language": "en",
"value": "Adding a map to view nearby places"
}
]
}
]
保留已完成功能列表
如果您在JSON中为功能添加isFinished
为true
,用户将看不到投票视图,也不会发出API调用来获取投票。这是一个可选值,默认值为false
。
使用Swift Package Manager添加Roadmap
在Xcode的包管理器中添加https://github.com/AvdLee/Roadmap.git
。
创建Roadmap配置实例
按照文档创建新的Roadmap配置:
let configuration = RoadmapConfiguration(
roadmapJSONURL: URL(string: "https://simplejsoncms.com/api/k2f11wikc6")!
)
您也可以选择性地传递一个请求,以便处理更高级的端点,例如受OAuth保护的端点:
var request = URLRequest(url: URL(string: "https://simplejsoncms.com/api/k2f11wikc6")!)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer 1234567890", forHTTPHeaderField: "Authorization")
let configuration = RoadmapConfiguration(
roadmapRequest: request
)
使用配置构建视图
在RoadmapView
中使用配置:
struct ContentView: View {
let configuration = RoadmapConfiguration(
roadmapJSONURL: URL(string: "https://simplejsoncms.com/api/k2f11wikc6")!,
namespace: "yourappname" // 默认为您应用的bundle id
allowVotes: true, // 将此设置为false以只读模式呈现路线图
allowSearching: false // 通过添加搜索栏允许用户筛选功能列表
)
var body: some View {
RoadmapView(configuration: configuration)
}
}
样式
通过使用RoadmapStyle
初始化RoadmapConfiguration
,您可以创建自己的样式。
public struct RoadmapStyle {
/// 用于赞成按钮的图像
let upvoteIcon : Image
/// 用于取消投票按钮的图像
let unvoteIcon : Image
/// 用于功能的字体
let titleFont : Font
/// 用于计数标签的字体
let numberFont : Font
/// 用于状态视图的字体
let statusFont : Font
/// 状态视图的色调颜色
let statusTintColor: (String) -> Color
/// 赞成按钮的圆角半径
let radius : CGFloat
/// 每个单元格的背景颜色
let cellColor : Color
/// 投票时文本和图标的颜色
let selectedForegroundColor : Color
/// 路线图视图的主色调
let tintColor : Color
public init(upvoteIcon: Image,
unvoteIcon: Image,
titleFont: Font,
numberFont: Font,
statusFont: Font,
statusTintColor: @escaping (String) -> Color = { _ in Color.primary },
cornerRadius: CGFloat,
cellColor: Color = Color.defaultCellColor,
selectedColor: Color = .white,
tint: Color = .accentColor) {
self.upvoteIcon = icon
self.titleFont = titleFont
self.numberFont = numberFont
self.statusFont = statusFont
self.statusTintColor = statusTintColor
self.radius = cornerRadius
self.cellColor = cellColor
self.selectedForegroundColor = selectedColor
self.tintColor = tint
}
}
模板
如果您不想配置自己的样式,也可以使用其中一个模板。您可以选择Standard
、Playful
、Classy
和Technical
中的任何一个,选择最适合您应用的模板。
示例
struct ContentView: View {
let configuration = RoadmapConfiguration(
roadmapJSONURL: URL(string: "https://simplejsoncms.com/api/k2f11wikc6")!,
namespace: "roadmap",
style: RoadmapTemplate.playful.style, // 您也可以创建自己的RoadmapStyle
)
var body: some View {
RoadmapView(configuration: configuration)
}
}
保存投票
默认情况下,Roadmap 将使用免费计数 API来存储投票,您可以查看他们的网站以获取更多信息。系统会为您提供一个命名空间,使用您应用程序的包标识符,但您可以在初始化 RoadmapConfiguration
时覆盖它。
let configuration = RoadmapConfiguration(
roadmapJSONURL: URL(string: "https://simplejsoncms.com/api/k2f11wikc6")!,
namespace: "my-custom-namespace"
)
定义自定义投票服务
如果您更愿意使用自己的 API,可以创建一个符合 FeatureVoter
协议的新结构体。这需要两个必要的函数来检索当前投票数和投新的一票。
struct CustomFeatureVoter: FeatureVoter {
var count = 0
func fetch(for feature: RoadmapFeature) async -> Int {
// 在此处查询您 API 的数据
return count
}
func vote(for feature: RoadmapFeature) async -> Int? {
// 在此处向您的 API 推送数据
count += 1
return count
}
}
然后您可以将这个结构体的实例传递给 RoadmapConfiguration
。
let configuration = RoadmapConfiguration(
roadmapJSONURL: URL(string: "https://simplejsoncms.com/api/k2f11wikc6")!,
voter: CustomFeatureVoter()
)
常见问题
Roadmap 能防止用户多次投票吗?
是的,如果用户已经为某个功能投票,他们将无法在您的应用内再次投票。但如果用户真的想操纵您的投票,他们可以拦截您的网络流量并重放 API 调用。
可以自定义 Roadmap 以适应我的应用外观和感觉吗?
Roadmap 提供了四种不同的预配置样式,以适应大多数应用。您可以更改色调、赞成图像等。
支持哪些操作系统版本?
为了保持 Roadmap 的开发简单有趣,我们决定目前支持 iOS 15 及以上版本,以及 macOS Monterey 和 Ventura。
我可以按最多投票对路线图进行排序吗?
目前功能列表是随机加载的。我们的想法是这可以防止对得票最多的功能产生偏见。我们将来会考虑如何实现这一点,但由于投票是在视图加载后检索的,我们需要进一步研究。
如果使用 Roadmap,我需要更改应用程序隐私报告吗?
Roadmap 不进行任何分析或跟踪。如果用户对某个功能投票,它只会在计数 API 上增加一个数字。不存储任何标识符,甚至匿名标识符也不存储。
愚蠢的人有可能操纵我的路线图吗?
是的,我们希望保持 Roadmap 的设置尽可能简单。如果您担心竞争对手(或非常想要特定功能的用户)干扰您的优先列表,也许应该使用其他工具。
我可以帮助贡献吗?
当然可以!我们非常欢迎您解决任何开放的问题。我们会相应地审查您的拉取请求。
使用 Roadmap 的项目
- MacWhisper
- RocketSim
- NowPlaying
- Stuny
- Stock Analyzer
- Super Coder
- SF Symbols Game
- Gola
- Rahhal | رحَّال
- Cronica
- Photo Club Waalre
- Leximio
如果您已将 Roadmap 集成到您的应用中,并希望将其添加到此列表中,请提交拉取请求。
作者
这个库是由 Jordi Bruin、Hidde van der Ploeg 和 Antoine van der Lee 合作创建的。
许可证
Roadmap 根据 MIT 许可证提供。有关更多信息,请参阅 LICENSE 文件。