Swift closures - порядок выполнения кода в отношении присвоения значения - PullRequest
0 голосов
/ 27 сентября 2018

Я хотел бы детально узнать правильный порядок выполнения при работе с данными в обработчике завершения.У меня есть следующее определение функции в моем классе Event:

@nonobjc public class func fetchEvents(completion: @escaping ([Event]) -> () = { _ in }) -> [Event] {
    let fetch = self.fetchEventRequest()

    var entities: [Event] = []
    context.perform {
        entities = try! fetch.execute()
        completion(entities)
    }
    return entities
}

И я вызываю вышеупомянутую функцию из моего контроллера представления следующим образом:

events = MyEvents.fetchEvents() { entities in
        if (entities.count == 0) {
            self.events = Event.getEventsFromAPI()
        } 
        print(events.count) - // returns 0 at this point
        self.eventsTableView.reloadData()
    }

После вызова self.eventsTableView.reloadData() my events переменная по-прежнему пуста.Я бы предположил, что, поскольку обработчик завершения выполняется после успешного выполнения кода внутри функции, переменной events уже было бы присвоено возвращаемое значение, нет?

1 Ответ

0 голосов
/ 27 сентября 2018

Вот краткий обзор вашей рассматриваемой функции:

...
context.perform {
    entities = try! fetch.execute()
    completion(entities)
}
return entities

Swift видит это так:

  1. Вызовите эту context.perform функцию
  2. Вызовreturn entities
  3. Обработка вывода context.perform внутри замыкания

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

Самое простое было бы изменить вашу функцию с:

@nonobjc public class func fetchEvents(completion: @escaping ([Event]) -> () = { _ in }) -> [Event]

на:

@nonobjc public class func fetchEvents(completion: @escaping ([Event]) -> () = { _ in })

Разница здесь заключается в удалении возврата [Event].

Затем внутри вашей функции удалите строку return entities.

Теперь у вас есть асинхронная функция,поэтому все, что вы используете для вызова, должно использовать закрытие для значения [Event].

self.events = Event.getEventsFromAPI() становится примерно таким:

Event.getEventsFromAPI() = { [weak self] events in
    self?.events = events
}
...