SwiftUI - 获取远程 JSON 数据中的数据以在 App 启动时刷新
SwiftUI - Get data in remote JSON data to refresh on App startup
我是菜鸟(我的 code/model 目前会显示它,所以请放轻松!)。
我正在尝试创建一个食谱风格 (cenotes) 应用程序。
为了更新数据,我有一个远程 json 文件,因此用户无需重新安装即可获取更新的数据。
应用程序成功检索并解析数据(成功!),但仅限首次安装时。
在线更改时不是后续刷新数据。我尝试使用 .onAppear 和 .refreshable 均未成功。我需要删除应用程序并重新安装才能获取更新的数据。
以下是我文件的一些编辑版本:有人可以帮忙吗?我认为我只是有一个 @StateObject/@EnvironmentObject 或类似的东西不正确,但无法发现错误。
Locations.swift
import Foundation
class Locations: ObservableObject {
@Published var locations = [Location]()
init() {
load()
}
func load() {
let url = URL(string: "https://www.i-love-tulum.com/cenotes/locations.json")!
URLSession.shared.dataTask(with: url) {(data,response,error) in
do {
if let d = data {
let data = try JSONDecoder().decode([Location].self, from: d)
DispatchQueue.main.async {
self.locations = data
}
} else {
print("No Data")
}
} catch {
print ("Error")
}
}.resume()
} }
Location.swift - VM
import Foundation
struct Location: Codable, Identifiable {
var id: String
let heroPicture: String
}
App.swift - 应用程序打开此选项卡视图
import SwiftUI
@main struct App: App {
@StateObject var locations = Locations()
@State private var selection = 1
var body: some Scene {
WindowGroup {
TabView (selection:$selection) {
NavigationView {
ListView()
}
.tabItem {
Image(systemName: "drop.circle")
Text("Cenotes")
} .tag(1)
}
.environmentObject(locations)
}
} }
ListView.swift - 第一个选择的选项卡是这个视图 - 这些位置在初始安装后不会更新:
import SwiftUI import MapKit
struct ListView: View {
@EnvironmentObject var locations: Locations
var body: some View {
VStack {
GeometryReader { geo in
ScrollView {
LazyVStack (alignment: .leading) {
ForEach (locations: locations.locations) { location in
NavigationLink (
destination: ContentView(location: location),
label: {
Image(location.heroPicture)
}
.navigationTitle("Cenotes")
.navigationBarTitleDisplayMode(.inline)
} }
一切都已设置好并且运行良好。这会在列表中添加两个按钮,以删除所有条目并重新加载。也许这有帮助。
struct ListView: View {
@EnvironmentObject var locations: Locations
var body: some View {
List {
ForEach (locations.locations) { location in
NavigationLink {
Text("Content View here ...")
} label: {
VStack(alignment: .leading) {
Text(location.name).font(.title)
Text(location.aka).foregroundColor(.secondary)
}
}
.navigationTitle("Cenotes")
.navigationBarTitleDisplayMode(.inline)
}
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Delete all") {
locations.locations = []
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button("Reload") {
locations.load()
}
}
}
}
}
每次都尝试重新加载并跳过所有缓存:
更新,现在工作:)
func load() {
let url = URL(string: "https://www.i-love-tulum.com/cenotes/locations.json")!
let config = URLSessionConfiguration.default
config.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
let session = URLSession.init(configuration: config)
session.dataTask(with: url) {(data,response,error) in
do {
if let d = data {
let data = try JSONDecoder().decode([Location].self, from: d)
DispatchQueue.main.async {
self.locations = data
}
} else {
print("No Data")
}
} catch {
print ("Error")
}
}.resume()
我是菜鸟(我的 code/model 目前会显示它,所以请放轻松!)。
我正在尝试创建一个食谱风格 (cenotes) 应用程序。
为了更新数据,我有一个远程 json 文件,因此用户无需重新安装即可获取更新的数据。
应用程序成功检索并解析数据(成功!),但仅限首次安装时。
在线更改时不是后续刷新数据。我尝试使用 .onAppear 和 .refreshable 均未成功。我需要删除应用程序并重新安装才能获取更新的数据。
以下是我文件的一些编辑版本:有人可以帮忙吗?我认为我只是有一个 @StateObject/@EnvironmentObject 或类似的东西不正确,但无法发现错误。
Locations.swift
import Foundation
class Locations: ObservableObject {
@Published var locations = [Location]()
init() {
load()
}
func load() {
let url = URL(string: "https://www.i-love-tulum.com/cenotes/locations.json")!
URLSession.shared.dataTask(with: url) {(data,response,error) in
do {
if let d = data {
let data = try JSONDecoder().decode([Location].self, from: d)
DispatchQueue.main.async {
self.locations = data
}
} else {
print("No Data")
}
} catch {
print ("Error")
}
}.resume()
} }
Location.swift - VM
import Foundation
struct Location: Codable, Identifiable {
var id: String
let heroPicture: String
}
App.swift - 应用程序打开此选项卡视图
import SwiftUI
@main struct App: App {
@StateObject var locations = Locations()
@State private var selection = 1
var body: some Scene {
WindowGroup {
TabView (selection:$selection) {
NavigationView {
ListView()
}
.tabItem {
Image(systemName: "drop.circle")
Text("Cenotes")
} .tag(1)
}
.environmentObject(locations)
}
} }
ListView.swift - 第一个选择的选项卡是这个视图 - 这些位置在初始安装后不会更新:
import SwiftUI import MapKit
struct ListView: View {
@EnvironmentObject var locations: Locations
var body: some View {
VStack {
GeometryReader { geo in
ScrollView {
LazyVStack (alignment: .leading) {
ForEach (locations: locations.locations) { location in
NavigationLink (
destination: ContentView(location: location),
label: {
Image(location.heroPicture)
}
.navigationTitle("Cenotes")
.navigationBarTitleDisplayMode(.inline)
} }
一切都已设置好并且运行良好。这会在列表中添加两个按钮,以删除所有条目并重新加载。也许这有帮助。
struct ListView: View {
@EnvironmentObject var locations: Locations
var body: some View {
List {
ForEach (locations.locations) { location in
NavigationLink {
Text("Content View here ...")
} label: {
VStack(alignment: .leading) {
Text(location.name).font(.title)
Text(location.aka).foregroundColor(.secondary)
}
}
.navigationTitle("Cenotes")
.navigationBarTitleDisplayMode(.inline)
}
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Delete all") {
locations.locations = []
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button("Reload") {
locations.load()
}
}
}
}
}
每次都尝试重新加载并跳过所有缓存:
更新,现在工作:)
func load() {
let url = URL(string: "https://www.i-love-tulum.com/cenotes/locations.json")!
let config = URLSessionConfiguration.default
config.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
let session = URLSession.init(configuration: config)
session.dataTask(with: url) {(data,response,error) in
do {
if let d = data {
let data = try JSONDecoder().decode([Location].self, from: d)
DispatchQueue.main.async {
self.locations = data
}
} else {
print("No Data")
}
} catch {
print ("Error")
}
}.resume()