在完成处理程序后执行的代码被称为

问题描述:

为什么在完成处理程序被调用后继续执行?在完成处理程序后执行的代码被称为

请参阅代码中的注释。查看代码路径以获得#1。此时我期待代码调用完成处理程序complete(),并从函数返回,从而阻止#2的执行。然而,#2的代码似乎仍然被触发。任何想法为什么这个OS发生?

func syncSessionLog(withCompletion complete: @escaping ((Bool, String?) -> Void)) { 

    ... bunch of code 

     managedObjectContext.performAndWait { 
      let trackFetchRequest: NSFetchRequest<NSFetchRequestResult> = Track.fetchRequest() 
      let trackPredicate = NSPredicate(format: "id == \(session.track_id)") 

      trackFetchRequest.predicate = trackPredicate 
      trackFetchRequest.fetchLimit = 1; 

      do { 
       let foundTrack = try self.managedObjectContext.fetch(trackFetchRequest) as! [Track] 
       if foundTrack.count < 1 { 
        self.debug.log(tag: "SessionManager", content: "not found tID: \(session.track_id)") 

        //#1 When not found, complete is called, yet the code still manages to reach "do stuff" down the bottom. 

        complete(false, "Not found") 
        return 
       } 

       associatedTrack = foundTrack[0] 
      } 
      catch { 
       self.debug.log(tag: "SessionManager", content: "Failed to get Track object from Core Data: \(error.localizedDescription)") 
       fatalCoreDataError(error) 
       complete(false, "Failed to retrieve") 
      } 
     } 

     //#2 do stuff with associatedTrack 
+0

是否抛出异常?你的catch函数调用'complete'并且不返回(所以执行流向#2)。 – par

+0

返回只会让您退出等待模块。 #2将继续流动。如果要在完成后阻止执行,则需要等待函数外的布尔标志。根据你自己的逻辑改变它的值,然后在#2检查标志的值,如果你需要的话继续。不要忘记宣布国旗为块。 –

+1

不,''associatedTrack'设置为零。 :/我hackishly解决,如果通过检查'associatedTrack'是否为零,然后继续。不过,我想知道这里真正发生了什么。 – toast

return将退出当前上下文,其是与相关联的performAndWait封闭件的出。在关闭返回之后,执行继续执行performAndWait之后的下一个语句,即#2中的任何内容。

您可以从点#代码移动2 关闭

+0

不应该'那么'完成()'调用停止执行到达''返回'无论如何? – toast

+0

编号'complete'调用完成处理程序,但在完成处理程序返回后,您将回到完成处理程序调用后的语句(返回值) - 但这只是退出关闭。 – Paulw11

+1

ohhhh。我期望调用完成处理程序来返回以及执行闭包。 – toast

它很简单 - return语句块里面,所以它从块返回,而不是从外面方法。如果该块有一些返回值,它将更加明显。

因此,您的代码中不需要此return。您将需要设置一个Bool标志来指示块执行的结果,并在#2中采取同样的行动。

+0

不应该说'complete()'调用从无论如何到达'return'的停止执行吗? – toast

+1

不,为什么? 'complete()'是另一个块,不是该语言的关键字。它的名字可能是误导性的,但它只是一个命名约定。它可以很好地命名为'inform()'或其他任何东西。你应该像方法一样考虑块。如果你调用'self.complete()',你不会期望代码停止,你会吗? – Losiowaty

+0

谢谢,我向你投了票,因为我无法接受你们俩。谢谢。 – toast