You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Swift中调用GitHub API实现macOS应用版本更新检测?

问题根源

你遇到的报错已经明确指向核心问题:你将GitHub API返回的单个字典对象错误当作数组进行解码。你调用的/repos/{owner}/{repo}/releases/latest接口返回的是单个Release信息结构体,不是Release数组,因此用[TaskEntry].self作为解码类型必然触发类型不匹配错误。

修复步骤

1. 调整数据模型与状态变量

将原TaskEntry替换为语义更清晰的GitHubRelease模型,同时把存储结果的状态变量从数组改为单个可选对象:
Model.swift代码:

import Foundation

struct GitHubRelease: Codable {
    let id: Int
    let tag_name: String
    let name: String
    // 后续需要更新描述、安装包下载链接等字段,只要和GitHub返回字段名对应即可继续扩展
}

ContentView.swift中状态变量修改为:

@State var latestRelease: GitHubRelease?

2. 优化请求与解码逻辑

  • 移除不安全的try!,改用do-catch捕获解码错误,避免App直接崩溃
  • GitHub API要求必须携带User-Agent请求头,否则会返回403拒绝访问
  • 解码类型改为单个GitHubRelease.self而非数组类型

完整loadData方法代码:

func loadData() {
    guard let url = URL(string: "https://api.github.com/repos/NCX-Programming/RNGTool/releases/latest") else {
        print("无效URL")
        return
    }
    var request = URLRequest(url: url)
    // 这里替换为你App的Bundle ID即可
    request.setValue("your_app_bundle_id", forHTTPHeaderField: "User-Agent")

    URLSession.shared.dataTask(with: request) { data, response, error in
        if let error = error {
            print("请求出错: \(error.localizedDescription)")
            return
        }
        guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
            print("响应无效")
            return
        }
        guard let data = data else {
            print("返回数据为空")
            return
        }
        do {
            let release = try JSONDecoder().decode(GitHubRelease.self, from: data)
            DispatchQueue.main.async {
                self.latestRelease = release
                // 此处可添加版本对比逻辑:取出release.tag_name和本地App版本对比即可
                // 本地版本号获取方法:Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
            }
        } catch {
            print("解码失败: \(error)")
            // 调试时可打开下面的注释打印返回的原始JSON内容排查问题
            // if let jsonStr = String(data: data, encoding: .utf8) {
            //     print("返回JSON: \(jsonStr)")
            // }
        }
    }.resume()
}

3. 调整View渲染逻辑

因为现在存储的是单个可选的版本信息,不用List布局,直接判断变量是否存在即可渲染:

var body: some View {
    VStack(alignment: .leading, spacing: 12) {
        if let latest = latestRelease {
            Text("最新版本号: \(latest.tag_name)")
            Text("版本名称: \(latest.name)")
            // 此处可添加更新提示弹窗、下载按钮等业务逻辑
        } else {
            Text("正在检查更新...")
        }
    }
    .padding()
    .onAppear(perform: loadData)
}

额外注意事项

  • GitHub API对未认证的请求有每小时60次的速率限制,个人自用的更新检测场景完全够用,若需要更高请求配额可以给请求添加Authorization头携带个人访问令牌
  • 版本号对比可以使用String的compare(_:options:)方法,传入.numeric参数即可按照数值规则正确对比版本号大小,比如正确识别1.2.0比1.1.9版本更高

内容的提问来源于stack exchange,提问作者NinjaCheetah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 22:09:04