您如何访问 Swift 中的 GitHub API?
How could you access the GitHub API in Swift?
我想在我的 macOS SwiftUI 应用程序中创建一个更新检测系统,方法是通过 [=45] 从 GitHub 中提取最新版本=] 然后比较标签。我将如何从 Swift 访问 API?我已经尝试使用 here, medium.com, here, swifttom.com and here, steveclarkapps.com 中的方法,但其中 none 完成了我正在尝试做的事情。
对于第一种方法,代码与提供的示例 API 一起运行,但不适用于 GitHub API 并且 returns 出现此错误:
Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))
方法 2 遇到同样的问题。
我什至无法获得足够的方法 3 代码来尝试它。
这是我根据 medium.com 方法改编的代码:
Model.swift
import Foundation
struct TaskEntry: Codable {
let id: Int
let tag_name: String
let name: String
}
ContentView.swift
import SwiftUI
struct ContentView: View {
@State var results = [TaskEntry]()
var body: some View {
List(results, id: \.id) { item in
VStack(alignment: .leading) {
Text(item.name)
}
}.onAppear(perform: loadData)
}
func loadData() {
guard let url = URL(string: "https://api.github.com/repos/NCX-Programming/RNGTool/releases/latest") else {
print("Invalid URL")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
/*if*/ let response = try! JSONDecoder().decode([TaskEntry].self, from: data) /*{*/
DispatchQueue.main.async {
self.results = response
}
return
/*}*/
}
}.resume()
}
}
注释掉的代码和看起来无关紧要的变量名只是剩下的。
OS: macOS 大苏尔 11.6
Xcode版本:13.0
在浏览器中打开:
https://api.github.com/repos/NCX-Programming/RNGTool/releases/latest
你会注意到它不是一个数组而是一个对象。你应该像这样解码一个对象:
JSONDecoder().decode(TaskEntry.self, from: data)
编辑:
这需要你改变你的看法。请注意,这不再是 List
,因为您不再获取数组,而是获取单个项目:
struct TaskEntry: Codable {
let id: Int
let tagName: String
let name: String
}
struct ContentView: View {
@State var entry: TaskEntry? = nil
var body: some View {
VStack(alignment: .leading) {
if let entry = entry {
Text("\(entry.id)")
Text(entry.name)
Text(entry.tagName)
} else {
ProgressView()
}
}
.onAppear(perform: loadData)
}
func loadData() {
guard let url = URL(string: "https://api.github.com/repos/NCX-Programming/RNGTool/releases/latest") else {
print("Invalid URL")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
// TODO: Handle data task error
return
}
guard let data = data else {
// TODO: Handle this
return
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let response = try decoder.decode(TaskEntry.self, from: data)
DispatchQueue.main.async {
self.entry = response
}
} catch {
// TODO: Handle decoding error
print(error)
}
}.resume()
}
}
注意:我还做了一些其他改进
- 使用JSON解码器将蛇形大小写转换为骆驼形大小写
- 添加了 do catch 块,这样您的应用程序就不会崩溃
- 解码前检查错误
- 添加了加载指示器(必须在 else 中添加一些东西)
然而,
正如我们的讨论,您可能调用了错误的端点。该端点返回的不是数组而是单个对象,您可以这样说,因为 JSON 响应以 {
而不是 [
开头
我已经调整了我的答案以更改端点我认为你应该打电话给:
struct TaskEntry: Codable {
let id: Int
let tagName: String
let name: String
}
struct ContentView: View {
@State var results: [TaskEntry]? = nil
var body: some View {
if let results = results {
List(results, id: \.id) { item in
VStack(alignment: .leading) {
Text(item.name)
}
}
} else {
VStack(alignment: .leading) {
ProgressView()
.onAppear(perform: loadData)
}
}
}
func loadData() {
guard let url = URL(string: "https://api.github.com/repos/NCX-Programming/RNGTool/releases") else {
print("Invalid URL")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
// TODO: Handle data task error
return
}
guard let data = data else {
// TODO: Handle this
return
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let response = try decoder.decode([TaskEntry].self, from: data)
DispatchQueue.main.async {
self.results = response
}
} catch {
// TODO: Handle decoding error
print(error)
}
}.resume()
}
}
我想在我的 macOS SwiftUI 应用程序中创建一个更新检测系统,方法是通过 [=45] 从 GitHub 中提取最新版本=] 然后比较标签。我将如何从 Swift 访问 API?我已经尝试使用 here, medium.com, here, swifttom.com and here, steveclarkapps.com 中的方法,但其中 none 完成了我正在尝试做的事情。
对于第一种方法,代码与提供的示例 API 一起运行,但不适用于 GitHub API 并且 returns 出现此错误:
Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))
方法 2 遇到同样的问题。
我什至无法获得足够的方法 3 代码来尝试它。
这是我根据 medium.com 方法改编的代码:
Model.swift
import Foundation
struct TaskEntry: Codable {
let id: Int
let tag_name: String
let name: String
}
ContentView.swift
import SwiftUI
struct ContentView: View {
@State var results = [TaskEntry]()
var body: some View {
List(results, id: \.id) { item in
VStack(alignment: .leading) {
Text(item.name)
}
}.onAppear(perform: loadData)
}
func loadData() {
guard let url = URL(string: "https://api.github.com/repos/NCX-Programming/RNGTool/releases/latest") else {
print("Invalid URL")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
/*if*/ let response = try! JSONDecoder().decode([TaskEntry].self, from: data) /*{*/
DispatchQueue.main.async {
self.results = response
}
return
/*}*/
}
}.resume()
}
}
注释掉的代码和看起来无关紧要的变量名只是剩下的。
OS: macOS 大苏尔 11.6 Xcode版本:13.0
在浏览器中打开:
https://api.github.com/repos/NCX-Programming/RNGTool/releases/latest
你会注意到它不是一个数组而是一个对象。你应该像这样解码一个对象:
JSONDecoder().decode(TaskEntry.self, from: data)
编辑:
这需要你改变你的看法。请注意,这不再是 List
,因为您不再获取数组,而是获取单个项目:
struct TaskEntry: Codable {
let id: Int
let tagName: String
let name: String
}
struct ContentView: View {
@State var entry: TaskEntry? = nil
var body: some View {
VStack(alignment: .leading) {
if let entry = entry {
Text("\(entry.id)")
Text(entry.name)
Text(entry.tagName)
} else {
ProgressView()
}
}
.onAppear(perform: loadData)
}
func loadData() {
guard let url = URL(string: "https://api.github.com/repos/NCX-Programming/RNGTool/releases/latest") else {
print("Invalid URL")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
// TODO: Handle data task error
return
}
guard let data = data else {
// TODO: Handle this
return
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let response = try decoder.decode(TaskEntry.self, from: data)
DispatchQueue.main.async {
self.entry = response
}
} catch {
// TODO: Handle decoding error
print(error)
}
}.resume()
}
}
注意:我还做了一些其他改进
- 使用JSON解码器将蛇形大小写转换为骆驼形大小写
- 添加了 do catch 块,这样您的应用程序就不会崩溃
- 解码前检查错误
- 添加了加载指示器(必须在 else 中添加一些东西)
然而,
正如我们的讨论,您可能调用了错误的端点。该端点返回的不是数组而是单个对象,您可以这样说,因为 JSON 响应以 {
而不是 [
我已经调整了我的答案以更改端点我认为你应该打电话给:
struct TaskEntry: Codable {
let id: Int
let tagName: String
let name: String
}
struct ContentView: View {
@State var results: [TaskEntry]? = nil
var body: some View {
if let results = results {
List(results, id: \.id) { item in
VStack(alignment: .leading) {
Text(item.name)
}
}
} else {
VStack(alignment: .leading) {
ProgressView()
.onAppear(perform: loadData)
}
}
}
func loadData() {
guard let url = URL(string: "https://api.github.com/repos/NCX-Programming/RNGTool/releases") else {
print("Invalid URL")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
// TODO: Handle data task error
return
}
guard let data = data else {
// TODO: Handle this
return
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let response = try decoder.decode([TaskEntry].self, from: data)
DispatchQueue.main.async {
self.results = response
}
} catch {
// TODO: Handle decoding error
print(error)
}
}.resume()
}
}