快速关闭和执行顺序

时间:2018-12-18 21:23:05

标签: ios swift closures

我正在努力尝试使用Swift创建一个用于我自己的教育目的的应用程序。

现在,我具有以下(期望的)执行顺序:

  1. TabView
  2. FirstViewController-TableView
  3. 签入CoreData
    • 如果数据存在,请使用闭包更新数组
    • 如果数据不存在,则使用Alamofire从API下载数据并将其存储到核心数据中
  4. SecondViewController-CollectionView
    • 检查图像数据是否存在于核心数据中,如果存在,则从那里加载,否则下载。

我最苦恼的问题是要知道闭包之后的代码是在闭包结束之后(同步)执行还是在闭包执行之前或同时执行。

例如:

FirstViewController

var response: [DDGCharacter]
//coreData is an instance of such class
coreData.load(onFinish: { response in //Custom method in another class
    print("Finished loading")
    self.response = response
})

print("Executed after loading data from Core Data")
//If no data is saved, download from API
if response.count == 0 {
    //Download from API
}

我已经完成了上述测试,并在10次运行中得到了相同的结果:

Finished loading
Executed after loading data from Core Data

在全部10个实例中,但这可能是因为负载没有花费太多时间来完成,因此似乎不是同步的。

所以我的问题是,是否将始终以该顺序执行该命令而与数据量无关?还是可能改变?我也做了一些调试,并且它们都在主线程上执行。我只想确保我的假设是正确的。

根据注释的要求,这是在load()方法中完成的实现:

func load(onFinish: ([DDGCharacter]) -> ()) {
    var characters: [DDGCharacter] = []

    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
        return
    }

    let managedContext = appDelegate.persistentContainer.viewContext

    let fetchRequest = NSFetchRequest<NSManagedObject> (entityName: "DDGCharacter")

    do {
        characters = try managedContext.fetch(fetchRequest) as! [DDGCharacter]
    } catch let error as NSError {
        print("Could not fetch. \(error), \(error.userInfo)")
    }

    onFinish(characters)
}

1 个答案:

答案 0 :(得分:1)

您对load(onFinish:)的实现非常令人惊讶并且过于复杂。幸运的是,这有助于证明您要问的问题。

闭包在有人调用时执行。因此,在您的情况下,onFinish在方法的末尾被调用,这使它成为同步的。成为“闭包”并不会使任何事情异步。它与调用函数相同。多次调用闭包是完全正常的(例如,map会这样做)。否则可能永远不会被调用。或者它可能被异步调用。从根本上讲,这就像传递一个函数。

当我说“它与匿名函数稍有不同”时,我指的是“关闭”的“关闭”部分。封闭“封闭”了当前环境。这意味着它将捕获闭包内部引用的局部范围内的变量。这与函数略有不同(尽管它比语法更重要的是语法,实际上在某些情况下函数可能会成为闭包)。

在这种情况下,更好的实现只是返回数组。