iosiphoneswiftuiviewcontrollerrunloop

UIViewController dismiss issue


I want to wait until dismiss animation completes but I don't want to use many blocks in my code, so I wrote this function in UIViewController extension (almost like this worked several years ago for me):

func dismissAnimated() {
   var comleted: Bool = false
   self.dismiss(animated: true) {
      comleted = true
   }

   while !comleted {
      RunLoop.current.run(mode: RunLoop.Mode.common, before: Date.distantFuture)
   }
}

so now instead of:

viewController.dismiss(animated: true) {
    // code after completion
}

I was supposed to write:

viewController.dismissAnimated()
// code after completion

But it doesn't dismiss view controller and doesn't enter into completion block.

I tried different RunLoop modes, tried different dates, tried inserting RunLoop.current.run into while condition, it didn't work. Any ideas how to accomplish this?

Edit:

And it worked on iOS 9 or something like this (may be with some code changes, because I can't find my source code). I start RunLoop.current.run to avoid blocking main thread. For instance, if I put completed = true in DispatchQue.main.asyncAfter , it will work, the issue is with dismiss


Solution

  • I tried again because I was curious and this solution actually works for me:

    @objc private func dismissTapped() {
    
        let dismissalTime = dismissAnimated()
        print("Dismissal took: %ld", abs(dismissalTime))
    
    }
    
    private func dismissAnimated() -> TimeInterval {
    
        let startDate = Date()
    
        var completed = false
        self.dismiss(animated: true) {
            completed = true
        }
    
        while !completed {
            RunLoop.current.run(mode: .default, before: .distantFuture)
        }
    
        return startDate.timeIntervalSinceNow
    
    }
    

    iOS 12.1.2 | Swift 4.2