0

I have a function in my SwiftUI app that waits 0.5 seconds for all of the data to come in and then rearranges the order of a list based on that data. This eventually works, but it makes for some weird jumping around for the first second or so of the list order because it is being changed after 0.5 seconds. The code looks like this:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                
    self.restaurants.sort {
        let waitTime1 = self.waitTimes[$0.id!] ?? -1
        let waitTime2 = self.waitTimes[$1.id!] ?? -1
        if (waitTime1 >= 0 && waitTime2 < 0) {
            return true
        } else if (waitTime1 < 0 && waitTime2 >= 0) {
            return false
        } else if (waitTime1 >= 0 && waitTime2 >= 0) {
            return waitTime1 < waitTime2
        } else if (waitTime1 < 0 && waitTime2 < 0) {
            return false
        } else {
            return false
        }         
    }
}

Essentially, I need wait 0.5 seconds for the self.waitTimes data to come in or else the list will sort with out it. I want to try to show a ProgressView over the regular content view while this sorting is taking place, for about a second. I tried putting all my content in a separate content view and then setting it equal to a ProgressView for a second then setting it back to the original content, but this didn't work:

contents = AnyView(ProgressView())
             
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    contents = AnyView(origContents)
                 
    self.restaurants.sort {
        let waitTime1 = self.waitTimes[$0.id!] ?? -1
        let waitTime2 = self.waitTimes[$1.id!] ?? -1
        if (waitTime1 >= 0 && waitTime2 < 0) {
            return true
        } else if (waitTime1 < 0 && waitTime2 >= 0) {
            return false
        } else if (waitTime1 >= 0 && waitTime2 >= 0) {
            return waitTime1 < waitTime2
        } else if (waitTime1 < 0 && waitTime2 < 0) {
            return false
        } else {
            return false
        }
                                    
   }
}

Does anyone have any suggestions for how I can have the ProgressView be displayed for a second while my list gets sorted? Thank you

kmcclenn
  • 127
  • 11

1 Answers1

0

Try this: the following code will, after the view is called, wait one second until showing the actual content.

struct TestView: View{

@State var showContent = false 

var body: some View{
NavigationView{
VStack{
 if showContent{
 /*This is placeholder content - display what you eventually want displayed 
 here*/
  Text("Content")

NavigationLink(destination: SomeOtherView(),
                   isActive: self.$childViewShown) {
      Text("Other View")
    }
 } else {
  ProgressView()
 }
 }.onAppear{
  DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
  showContent = true
}
}

.onChange(of: self.childViewShown) { show in
      if show {
        showContent = false
      } else {
        showContent = false
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
  showContent = true
      }
    }
}

}

}

The code for that SomeOtherView can be anything, as everything important happens in the first view. If you wanted, you could pass in $showContent as a binding to the other view, removing potential errors before diappear code is called. In the other view, you would need: @Binding var showContent: Bool, and you would call it in the first like: SomeOtherView(showContent: $showContent). Then, you could set showContent to false when the other view appeared.

Citation for the updated code that forces a refresh: https://stackoverflow.com/a/67696357/18457910

Citation, a good source for time delays: https://www.hackingwithswift.com/example-code/system/how-to-run-code-after-a-delay-using-asyncafter-and-perform.

  • Thank you this does work. However, it only works on initial startup of the app. Do you know how I can get this same thing to happen when I navigate back to the home page as well? – kmcclenn May 24 '22 at 03:12
  • I updated the answer, does this now work? Checking out some of the answers on that first citation might be helpful too - they are all great ways to detect when a view disappears, in which situation you then refresh the first view. –  May 24 '22 at 03:24
  • Is there a way to do this though without including that top navigation link? I have a list of navigation links and I don't think it will work to put all of them at the top like you had it. Maybe I am reading it wrong though. – kmcclenn May 24 '22 at 03:53