Удалить ссылку на замыкание, когда оно все еще выполняет определенную задачу в Swift

#swift #closures

#swift #замыкания

Вопрос:

Я создал замыкание, и значение возвращается через некоторое время. В течение этого периода я снова вызываю это закрытие с другими данными. Проблема в том, что получен ответ на закрытие, но также получен предыдущий ответ на закрытие. Как я могу удалить ссылку на первое закрытие, чтобы я мог получить ответ только от последнего закрытия?

Вот мой код:

 func getUsers() {

    self.getUsers = GetUsers()

    self.getUsers.getUsersData(latitude: Double(latitude)!, longitude: Double(longitude)!, range:range)
     { (usersArray, error) in

    }

}
  

Обновить:

Я передал текущий объект из замыкания, и, похоже, он работает нормально. Вот обновленный код:

 func getUsers() {

    self.getUsers = GetUsers()

    self.getUsers.getUsersData(latitude: Double(latitude)!, longitude: Double(longitude)!, range:range)
     {[weak self] (usersArray, error, getUsersObject) in

      if let strongSelf = self {
         if strongSelf.getUsers != getUsersObject {
           return
         }
       }
    }

}
  

Если возвращаемый объект из замыкания не соответствует повторно инициализированному объекту, я просто возвращаю его.

Ответ №1:

Это будет зависеть от реализации getUsersData . В общем, вероятно, нет способа отменить обратный вызов. Лучшее, что вы можете сделать, это заставить код обратного вызова проверять какой-то флаг или идентификатор при его запуске и ничего не делать, если проверка завершается неудачей.

Пример:

     ids.append("do this one")
    delay(2) { [weak self] in
        let id = "do this one"
        if let s = self, s.ids.contains(id) {
            print(id)
        }
    }
    ids.append("don't do this one")
    delay(2) { [weak self] in
        let id = "don't do this one"
        if let s = self, s.ids.contains(id) {
            print(id)
        }
    }
    ids.remove(at:1) // cancel this one
  

Выводит «Я сделаю это», но не выводит «не делайте этого». Это было бы, но мы отменили это, удалив его из ids массива.

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

1. Я повторно инициализирую, используя self.getUsers = getUsers() . Это должно удалить ссылку на предыдущее замыкание, потому что объект теперь другой. Разве нет?

2. Нет, я не понимаю, почему это будет иметь какой-либо эффект. Закрытие было отправлено getUsersData и запланировано для обратного вызова давно. Вы не можете получить к нему доступ отсюда. Более того, закрытие является закрытием, поэтому любая среда, которую оно захватило, остается захваченной.

3. Я обновил свой ответ. Это работает. Но правильно ли это делать?

4. Ну, по сути, это то, что я сказал сделать: сопоставить с чем-то в текущем состоянии. Очень приятно. Единственная проблема заключается в том, что вы захватываете self , что может привести к утечке памяти. Вы заметите, что я был осторожен, чтобы не делать этого.

5. Спасибо за помощь! Я снова обновил свой ответ. Так ли это должно быть сделано?