Я хочу дождаться завершения анимации закрытия, но я не хочу использовать много блоков в своем коде, поэтому я написал эту функцию на UIViewController
extension
(почти так, как это работало у меня несколько лет назад):
func dismissAnimated() {
var comleted: Bool = false
self.dismiss(animated: true) {
comleted = true
}
while !comleted {
RunLoop.current.run(mode: RunLoop.Mode.common, before: Date.distantFuture)
}
}
так что теперь вместо:
viewController.dismiss(animated: true) {
// code after completion
}
Я должен был написать:
viewController.dismissAnimated()
// code after completion
Но он не отключает контроллер представления и не входит в блок завершения.
Я пробовал разные режимы RunLoop, пробовал разные даты, пытался вставить RunLoop.current.run в условие while, это не сработало. Любые идеи, как это сделать?
Редактировать:
И это работало на iOS 9 или что-то вроде этого (может быть с некоторыми изменениями кода, потому что я не могу найти свой исходный код). Я запускаю RunLoop.current.run
, чтобы не блокировать основной поток. Например, если я поставлю completed = true
в DispatchQue.main.asyncAfter, он будет работать, проблема с dismiss
.
Он не отклоняется, потому что ваш цикл while !completed
остановил основной поток, и обновление пользовательского интерфейса происходит в основном потоке. Что плохого в том, чтобы запускать любой код, который вам нужен, внутри замыкания завершения dismiss
?
self.dismiss(animated: true) {
runSomeCode()
}
Если это действительно просто не использование блоков, может быть, это может быть решением?
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if self.navigationController?.isBeingDismissed ?? self.isBeingDismissed {
print("Dismissal completed...")
}
}
Нет, мне нужно выполнить задачу с помощью RunLoop, потому что код почти так работал раньше
На самом деле нашел решение, которое работает. Смотрите новый ответ.
Я попробовал еще раз, потому что мне было любопытно, и это решение действительно работает для меня:
@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 | Свифт 4.2
Спасибо, все работает, на самом деле работает только при тапе, если я вызываю rejectAnimated() из DispatchQueue.main, то не работает (dismiss работает, но завершение никогда не вызывалось), но я попробую разобраться
из-за решения об улучшении архитектуры я бы лучше использовал код без блока, в любом случае вопрос в том, как заставить это решение работать. И это работало на iOS 9 или что-то вроде этого (может быть с некоторыми изменениями кода, потому что я не могу найти свой исходный код). Я запускаю runLoop, чтобы не блокировать основной поток. Например, если я поставлю DispatchQue.main.asyncAfter , это сработает, проблема с отклонением