简单用例:带有“最近”部分的状态列表,显示您最近导航到的那些状态。当点击链接时,动画开始但随后中止,可能是由于详细视图中的 onAppear 处理程序更改了模型的 recents 属性 - 这是由框架观察到的。日志消息表明框架不满意,但不清楚如何让它在添加到最近的延迟前约 2 秒的延迟......
import SwiftUI
class USState: Identifiable{
typealias ID = String
var id: ID
var name: String
init(_ name: String, id: String){
self.id = id
self.name = name
}
}
/** The model is a small set of us states for example purposes.
It also publishes a recents property which has a lifo stack of states that have been viewed.
*/
class StateModel: ObservableObject{
var states: [USState]
var stateMap: [USState.ID: USState]
@Published var recents = [USState]()
init(){
states = [
USState("California", id: "CA"),
USState("Georgia", id: "GA"),
USState("New York", id: "NY"),
USState("New Jersey", id: "NJ"),
USState("Montana", id: "MT")
]
stateMap = [USState.ID: USState]()
for state in states{
stateMap[state.id] = state
}
}
func addRecent(_ state: USState){
recents.removeAll(where: {$0.id == state.id})
recents.insert(state, at: 0)
}
func allExceptRecent() -> [USState]{
states.filter{ state in
recents.contains{
state.id == $0.id
} == false
}
}
}
/** A simple view to serve as the destination of a state link
*/
struct StateView: View{
@EnvironmentObject var stateModel: StateModel
var usState: USState
var body: some View{
Text(usState.name)
.onAppear{
DispatchQueue.main.async {
withAnimation {
stateModel.addRecent(usState)
}
}
}
}
}
/** A list of states broken into two sections, those that have been recently viewed, and the remainder.
Desired behavior is that when a state is tapped, it should navigate to its respective detail view and update the list of recents.
The issue is that the recents updating appears to confuse SwiftUI and the navigation is aborted.
*/
struct SidebarBounce: View {
@EnvironmentObject var model: StateModel
@SceneStorage("selectionStore") private var selectionStore: USState.ID?
struct Header: View{
var text: String
var body: some View{
Text(text)
.font(.headline)
.padding()
}
}
struct Row: View{
var text: String
var body: some View{
VStack{
HStack{
Text(text)
.padding([.leading, .trailing])
.padding([.top, .bottom], 8)
Spacer()
}
Divider()
}
}
}
var body: some View{
ScrollView{
LazyVStack(alignment: .leading, spacing: 0){
Section(
header: Header(text: "Recent")
){
ForEach(model.recents){place in
NavigationLink(
destination: StateView(usState: place),
tag: place.id,
selection: $selectionStore
){
Row(text: place.name)
}
.id("Recent \(place.id)")
}
}
Section(
header: Header(text: "All")
){
ForEach(model.allExceptRecent()){place in
NavigationLink(
destination: StateView(usState: place),
tag: place.id,
selection: $selectionStore
){
Row(text: place.name)
}
.id("All \(place.id)")
}
}
}
}
}
}
struct BounceWrap: View{
let model = StateModel()
var body: some View{
NavigationView{
SidebarBounce()
.navigationTitle("Aborted Navigation")
Text("Nothing Selected")
}
.environmentObject(model)
}
}
@main
struct DemoApp: App {
var body: some Scene {
WindowGroup {
BounceWrap()
}
}
}
注意:这必须作为应用程序(iPhone 或模拟器)而不是在预览中运行。