Ios Swift-JSON中的列表仅在视图调用时出现
我的应用程序中有一部分是通过调用外部API构建的,该API返回一个JSON对象,然后通过应用程序中的列表显示该对象。下面可以看到这方面的代码、请求函数以及数据的实际SwiftUI显示Ios Swift-JSON中的列表仅在视图调用时出现,ios,swift,swiftui,Ios,Swift,Swiftui,我的应用程序中有一部分是通过调用外部API构建的,该API返回一个JSON对象,然后通过应用程序中的列表显示该对象。下面可以看到这方面的代码、请求函数以及数据的实际SwiftUI显示 struct ImportantBrokenView: View { @ObservedObject var fetcher = Fetcher() @EnvironmentObject var user: UserFetcher var body: some
struct ImportantBrokenView: View {
@ObservedObject var fetcher = Fetcher()
@EnvironmentObject var user: UserFetcher
var body: some View {
ZStack {
GeometryReader { metrics in
if (self.fetcher.hasFinished == true) {
VStack(alignment: .leading) {
HStack(alignment: .top){
VStack(alignment: .leading) {
NavigationView {
VStack(alignment:.center) {
Text("JSON List").font(.largeTitle).fontWeight(.bold).padding(.bottom, 0).padding(.top, 10)
Divider()
Spacer()
List{
ForEach(self.fetcher.fetched ?? []) { result in
VStack(alignment: .leading) {
VStack(alignment: .leading) {
Text(result.name).font(.system(size: 26)).fontWeight(.semibold).padding([.horizontal, .top])
}
}.listRowInsets(.init(top: 0, leading: 0, bottom: 0, trailing: 0))
}
}.frame(width: metrics.size.width * 1.0)
}
}
}
}
}
} else {
HStack(alignment: .center) {
VStack(alignment: .center) {
Text("Loading...")
}.frame(width: metrics.size.width * 1.0)
}.frame(width: metrics.size.width * 1.0, height: metrics.size.height * 1.0)
}
}.onAppear { self.fetcher.request(authToken: self.user.user!.accessToken) }
}
}
}
public struct Model2: Codable, Identifiable {
public let id: Int
public let name: String
}
public struct Model: Codable {
public let fetched: Model2
enum CodingKeys: String, CodingKey {
case fetched = "return"
}
}
public class Fetcher: ObservableObject {
@Published var fetched: Model?
public let objectWillChange = PassthroughSubject<Fetcher,Never>()
@Published var hasFinished: Bool = false {
didSet {
objectWillChange.send(self)
}
}
func request(authToken: String) {
guard let url = URL(string: "https://mywebsite.com/api/getdata") else { return }
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
let APIauthToken = "Bearer " + authToken
urlRequest.addValue(APIauthToken, forHTTPHeaderField: "Authorization")
urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
do {
if let d = data {
let decodedLists = try JSONDecoder().decode(Model.self, from: d)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
guard let _weakSelf = self else {return}
_weakSelf.fetched = decodedLists
}
} else {
print("No Data")
}
} catch {
print(error)
}
}.resume()
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
guard let _weakSelf = self else {return}
_weakSelf.hasFinished = true
}
}
}
struct ImportantBrokenView:视图{
@ObservedObject var fetcher=fetcher()
@EnvironmentObject变量用户:UserFetcher
var body:一些观点{
ZStack{
GeometryReader{中的度量
if(self.fetcher.hasFinished==true){
VStack(对齐:。前导){
HStack(对齐:。顶部){
VStack(对齐:。前导){
导航视图{
VStack(对齐:。中心){
文本(“JSON列表”).font(.largeTitle).fontwweight(.bold).padding(.bottom,0).padding(.top,10)
分隔器()
垫片()
名单{
ForEach(self.fetcher.fetched???[]){结果为
VStack(对齐:。前导){
VStack(对齐:。前导){
Text(result.name).font(.system(size:26)).fontwweight(.semibold).padding([.horizontal,.top])
}
}.listRowInsets(.init(顶部:0,前导:0,底部:0,尾随:0))
}
}.frame(宽度:metrics.size.width*1.0)
}
}
}
}
}
}否则{
HStack(对齐:。中心){
VStack(对齐:。中心){
文本(“加载…”)
}.frame(宽度:metrics.size.width*1.0)
}.frame(宽度:metrics.size.width*1.0,高度:metrics.size.height*1.0)
}
}.onAppear{self.fetcher.request(authToken:self.user.user!.accessToken)}
}
}
}
公共结构模型2:可编码、可识别{
公共出租id:Int
公共let名称:String
}
公共结构模型:可编码{
获取公共let:Model2
枚举编码键:字符串,编码键{
case fetched=“return”
}
}
公共类获取程序:ObservieObject{
@获取的已发布变量:模型?
public let objectWillChange=PassthroughSubject()
@已发布的变量hasFinished:Bool=false{
迪塞特{
objectWillChange.send(self)
}
}
func请求(authToken:String){
guard let url=url(字符串:https://mywebsite.com/api/getdata)否则{return}
var urlRequest=urlRequest(url:url)
urlRequest.httpMethod=“POST”
让APIauthToken=“承载人”+authToken
urlRequest.addValue(APIauthToken,forHTTPHeaderField:“授权”)
URL请求.addValue(“应用程序/json”,用于HttpHeaderField:“接受”)
urlRequest.addValue(“应用程序/json”,forHTTPHeaderField:“内容类型”)
URLSession.shared.dataTask(带:urlRequest){(数据、响应、错误)在
做{
如果设d=数据{
让decodedLists=try JSONDecoder().decode(Model.self,from:d)
DispatchQueue.main.asyncAfter(截止日期:.now()+1){[weak self]在中
guard let_weakSelf=self-else{return}
_weakSelf.fetched=解码列表
}
}否则{
打印(“无数据”)
}
}抓住{
打印(错误)
}
}1.简历()
DispatchQueue.main.asyncAfter(截止日期:.now()+1){[weak self]在中
guard let_weakSelf=self-else{return}
_weakSelf.hasFinished=true
}
}
}
当我运行这段代码时,它包含了生成JSON的所有代码,JSON用于派生Swift列表。当我运行这个时,我的列表是空的。当我返回导航堆栈,然后重新进入视图时,列表被占用。为什么?
如果非要我猜一猜,我会说这与DispatchQueue中包含的截止日期有关,请求和hasFinished响应的截止日期相同。不相关,但
弱自我->强自我
舞蹈毫无意义<代码>调度队列闭包不会导致保留周期<代码>数据任务异步工作,稍后执行完成处理程序。而不是奇怪的asyncAfter
表达式调用完成处理程序中的objectWillChange.send(self)
。不相关但弱自我->强自我
舞蹈是胡说八道<代码>调度队列闭包不会导致保留周期<代码>数据任务异步工作,稍后执行完成处理程序。而不是在完成处理程序中调用异常的asyncAfter
表达式objectWillChange.send(self)
。