【问题标题】:Swift closures - order of code execution in regards to value assignmentSwift 闭包 - 关于值分配的代码执行顺序
【发布时间】:2018-09-27 20:27:16
【问题描述】:

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

【问题讨论】:

    标签: ios swift completionhandler


    【解决方案1】:

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

    ...
    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
    }
    

    【讨论】:

    • 是的,这就是我最初想要的“解决方法”,但我也第二次猜测这是否是一种正确的方法,所以我很高兴看到这一点得到验证。谢谢解释
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-17
    • 1970-01-01
    • 2018-10-02
    • 1970-01-01
    • 2017-02-22
    • 1970-01-01
    相关资源
    最近更新 更多