首页 > 解决方案 > Swift 闭包 - 关于值分配的代码执行顺序

问题描述

我想详细了解在完成处理程序中处理数据时的正确执行顺序。我的 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()我的events变量仍然是空的。我假设由于完成处理程序在函数内的代码成功执行后执行,因此eventsvar 已经被分配了返回值,不是吗?

标签: iosswiftcompletionhandler

解决方案


以下是您的相关功能的摘要:

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

斯威夫特是这样看的:

  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
}

推荐阅读