Swift аварийно завершает работу при синхронном обновлении опубликованного значения внутри потока в iOS 13

#ios #swift #multithreading #asynchronous #combine

#iOS #быстрый #многопоточность #асинхронный #объединять

Вопрос:

У меня есть несколько шагов, которые нужно обработать синхронно. И значение, полученное в результате процесса, потребляется представлением. Он работает на iOS 14, но на iOS 13 он выходит из строя. Я использую объединение для публикации события для обновления значения, хранящегося внутри модели представления.

Это менеджер публикаций:

 final class PublisherManager {  static let shared = PublisherManager()  private var cancellable = Setlt;AnyCancellablegt;()   func mainPublisher() -gt; AnyPublisherlt;MainInput, Nevergt; {  mainSubject  .eraseToAnyPublisher()  }   let mainSubject = PassthroughSubjectlt;MainInput, Nevergt;()   enum MainInput {  case updateValue()  } }  

Это модель представления:

 final class ViewModel: ObservableObject {   @Published var status: Status = .checking   init() {  setObserver()  start()  }   private func setObserver() {  PublisherManager.shared.mainPublisher()  .receive(on: RunLoop.main)  .sink { [weak self] action in  guard let self = self else { return }  switch action {  case .updateValue:  self.updateValue()  }  }.store(in: amp;cancellable)  }   func start() {  let dispatchGroup = DispatchGroup()  let dispatchSemaphore = DispatchSemaphore(value: 1)   dispatchGroup.enter()  dispatchQueue.asyncAfter(deadline: DispatchTime.now()   1) {  dispatchSemaphore.wait()  self.getValues { //--gt; A process to call API  PublisherManager.shared.pushNotificationTroubleshooterSubject.send(.updateValue())  dispatchSemaphore.signal()  dispatchGroup.leave()  }  }    dispatchGroup.notify(queue: .main) {  // Notify  }  }    private func updateValue() {  status = .active  } }  

Когда я запускаю его, я получаю EXC_BAD_ACCESS в AppDelegate, но он вообще не выводит никаких ошибок в отладчике. Если я прокомментирую status = .active код, он не выйдет из строя.

Что я делаю не так и как я могу решить эту проблему?

Комментарии:

1. DispatchGroup и DispatchSemaphore заставить асинхронную задачу стать синхронной-ужасная практика. Особенно в Combine контексте, который делает обработку асинхронных задач такой удобной . DispatchGroup в любом случае, это неправильный API. Он был разработан для управления временем в группе (нескольких) асинхронных задач в цикле.

2. @vadian но тогда как с этим бороться? Я имею в виду, я пытался использовать dispatchQueue.sync , но иначе это не работает

3. Как я уже сказал, Combine предоставляет операторам возможность плавно объединять асинхронные задачи.

4. @vadian Хм, боюсь, я не совсем понял это, не могли бы вы, пожалуйста, рассказать немного подробнее?

Ответ №1:

Похоже на то, что вы сделали с DispatchGroup и DispatchSemaphore неправильно. Концепция объединения это похоже на асинхронное выполнение кода. Поэтому вместо того, чтобы использовать DispatchGroup и DispatchSemaphore просто использовать цепочку издателей с комбинациями и зависят ли действия от полученных событий

Комментарии:

1. Ответ неясен, пожалуйста, отредактируйте свой ответ, чтобы добавить некоторые детали, особенно код для описания рабочего процесса. Имейте в виду, что в вопросе указано, что он требует синхронизации задач, чтобы не перегружать вызов API чаще, чем один раз в секунду.