【发布时间】:2021-10-04 20:13:24
【问题描述】:
我在使用 onAppear 时遇到了一个奇怪的无限循环,我无法确定问题的根源。只有当视图是导航视图的详细视图时才会发生这种情况,但当它是根视图时它可以正常工作。 另一个有趣的事情是,如果我将详细视图包装在 NavigationView 中(所以,现在我们在导航视图中有一个导航视图),那么问题就不会再出现了。这是 SwiftUI 中的错误吗?从概念上讲,我的设计可以吗?我的意思是,使用类似 viewDidLoad 的 onAppear 来触发初始序列。 感谢您的建议。
这里是源代码。 ContentView.swift:
import SwiftUI
struct ContentView: View {
@StateObject var viewModel = ContentViewModel()
var body: some View {
NavigationView {
VStack {
Group {
switch viewModel.state {
case .loading:
Text("Loading...")
case .loaded:
HStack {
Text("Loaded")
Button("Retry") {
viewModel.fetchData()
}
}
}
}
.padding(.bottom, 20)
NavigationLink("Go to detail screen", destination: DetailView())
}
}
.onAppear() {
viewModel.fetchData()
}
}
}
class ContentViewModel: ObservableObject {
enum State {
case loading
case loaded
}
@Published var state: State = .loading
func fetchData() {
state = .loading
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.state = .loaded
}
}
}
这里是详细视图的代码:
import SwiftUI
struct DetailView: View {
@StateObject var viewModel = DetailViewModel()
var body: some View {
Group {
switch viewModel.state {
case .loading:
Text("Loading...")
case .loaded:
HStack {
Text("Loaded")
Button("Retry") {
viewModel.fetchData()
}
}
}
}
.onAppear() {
print("infinite loop here")
viewModel.fetchData()
}
}
}
class DetailViewModel: ObservableObject {
enum State {
case loading
case loaded
}
@Published var state: State = .loading
func fetchData() {
state = .loading
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.state = .loaded
}
}
}
我在这里附上项目: https://www.dropbox.com/s/5alokj3q81jbpj7/TestBug.zip?dl=0
我使用的是 Xcode 版本 12.5.1 (12E507) 和 iOS 14.5
非常感谢。
【问题讨论】:
-
似乎在 iOS 15 上按预期工作
-
这里一样,用 Xcode 13 beta 5 测试没有任何问题
-
为合唱添加另一个声音。 13RC、iOS 14.4 和 iOS 15。两者都经过测试。您确定这段代码导致了无限循环吗?
-
每个人都在评论它是如何在错误的 Xcode 版本上工作的。刚刚测试过,问题如 Xcode 12.5.1 和 iOS 14.5 所述。
-
好的,我刚刚意识到问题出在 Group 和 xcode 12 上。如果我使用 VStack,它可以工作。所以,这是一个苹果虫。