Как я могу освободить все элементы ссылок из массива?

Я пытаюсь создать механизм повторной попытки для наших сетевых вызовов. Я создал 2 класса. Один класс Retry и еще один менеджер в случае, если я захочу, я могу отменить все классы.

class Retry {
    var url: String
    var maxRetries: Int

    init (url: String, retryCount: Int){
        self.url = url
        self.maxRetries =  maxRetries
        poll()
        RetryManager.shared.add(self)
    }

    private func poll(){
        guard retryCount == 0 else{
            print("error")
        }
        getRequest()
    }

    private func getRequest(){
        // make network request
        // if no response is received poll again
    }


    func cancel(){
        maxRetries = 0
    }
}

Класс менеджера

class RetryManager{

    static let sharedInstance = RetryManager()
    var retries : [Retry?] = []

    private init(){
    }

    func register(retry: Retry){
        retries.append(retry)
    }
    func remove(retry: Retry){
        retry.cancel() // XX; Do I also need this or just removing it is fine?
        retries = retries.filter({$0 !== retry})
    }

    func cancelAll(){

        retries.forEach({$0?.cancel()}) // ZZ; Do I also need this? or just removing them is fine?
        retries.removeAll()

    }

}

Мои экземпляры повтора должны использоваться для совершения сетевых вызовов.

Мой главный вопрос касается механизма отмены. Будет ли делать RetryManager.shared.cancelAll() для освобождения? Или мне нужно запустить отмену или каждый экземпляр отмены (т.е. XX, ZZ также необходимы)?

В настоящее время все работает нормально, но я не уверен, что я буду работать, если у меня будет несколько указателей... мне нужно будет:

for index..<retries.count{
retries[index] = nil
}

Насколько я понимаю, это не поможет, так же, как и делать retries.removeAll()

Я также читаю В Swift, как установить каждый элемент внутри массива на нуль?, но ему было предложено открыть новый вопрос

Ответ 1

Не уверен, могу ли я ответить на ваш вопрос, но я постараюсь с наилучшим пониманием:).

Справочник Apple Swift на Автоматический подсчет ссылок (ARC) очень хорошо описывает ваш вопрос.

Обычно вам не нужно иметь массив опций,

var retries = [Retry]() 
...
retries.removeAll()

удалит все содержащиеся объекты и удалит ссылки на эти объекты. Из вашего контекста, представленного выше, я не понимаю, почему вам нужно объявить массив опций. Как вы знаете, опции Swift под капотом - это всего лишь типизированный класс-оболочка Optional<Type>, который не работает вокруг проблемы с распределением памяти.

Как ссылаются объекты массива?

Массив будет увеличивать количество ссылок на содержащиеся объекты на единицу, то есть сильную ссылку.

Чтобы гарантировать, что объекты в массиве будут освобождены, необходимо сделать их число ссылок равным нулю. Удаление их из массива сделает трюк, если ничего не ссылается на содержащиеся объекты.

Остерегайтесь эталонного цикла. В вашем случае вы не должны ссылаться на массив retries в экземпляре Retry. В противном случае, даже если вы установите массив retries на nil, массив и его содержащиеся объекты по-прежнему будут иметь сильную ссылку друг на друга, что означает, что их подсчет ссылок никогда не уменьшится до нуля, что приведет к утечке памяти.