0

I am calculate the escaping and non-escaping closures start and endtime inside the function. to see which function will end earlier.

func escapingexample (c: @escaping ()->Void){
    print("escapingex body starts" + String(clock()))

    c()
    print("escapingex body ends" + String(clock()))

}

class testesc{
    var x = 0;
    var completionHandlers = [(String)->Void]()

    func exampe(){
        print("exampe " + String(clock()))
        escapingexample {
            self.x = 4
            self.completionHandlers
            print("escapingex closure " + String(clock()))
        }
         
    }
    deinit {
        print("deinit testesc")
    }
}
var t_2 = testesc()

t_2.exampe();

but it looks that escaping closure not long living after calling function returns

escapingex body starts297900
escapingex closure 298193
escapingex body ends298265
  • "I am trying to escape a non-escaping closure , as the document suggests that these is not permitted." You seem to have provided your own answer. This is not permitted. That's intentional. Mark the closure with `@escaping`, or redesign to not require an escaping closure. Did you have some other question? It's not clear what you're asking here. – Rob Napier May 26 '21 at 19:03
  • i think this can make closure escape by this way, so is there a disadvantage of this? – user15262125 May 26 '21 at 19:07
  • What do you think is escaping here? `c` executes and then `nonescapingexample` returns. Nothing escapes. – Rob Napier May 26 '21 at 19:07
  • actually compiler must throwe an error in the closure also, like what it did like in the calling func. – user15262125 May 26 '21 at 19:10
  • What do you mean "compiler must throwe an error in the closure also?" What error must it throw? What do you think is escaping? – Rob Napier May 26 '21 at 19:11
  • You said "Actually If dispatching another thread inside the main/parent calling function, compiler throws an error." That's not true as a general rule. Do you have a complete example that shows what you mean? (There's no such thing as "dispatching another thread." You dispatch work items. They are only loosely related to threads in that they run on some generally unspecified thread.) – Rob Napier May 26 '21 at 19:13
  • https://i.stack.imgur.com/gSjXB.png this is what i get if i put dispatch in calling, but error not appears inside closure – user15262125 May 26 '21 at 19:15
  • What do you mean by "is there a disadvantage of this?" In your example that has an error, you're escaping a closure (you're passing a non-escaping `c` to a context that escapes the current scope). That's intentionally illegal. You must mark `c` as escaping. In your examples with no errors, you don't cause `c` to escape the current scope. You execute it and return it. So it's not escaping, and you don't need to mark it. – Rob Napier May 26 '21 at 19:17
  • "Escaping" means the closure exists longer than the current static scope. – Rob Napier May 26 '21 at 19:18
  • i have updated the sample, then can you summarize the difference between escaped and non escaped because it looks same, how can i measure the time than it wait more or how – user15262125 May 26 '21 at 19:20
  • Start with https://docs.swift.org/swift-book/LanguageGuide/Closures.html#ID546, and then see: https://stackoverflow.com/questions/39612938/what-is-difference-between-noescape-escaping-and-autoclosure https://stackoverflow.com/questions/61492303/in-swift-what-is-the-difference-between-and-escaping-void https://stackoverflow.com/questions/39504180/escaping-closures-in-swift – Rob Napier May 26 '21 at 19:22
  • The short version (from the Swift docs) is: "A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns." – Rob Napier May 26 '21 at 19:24
  • yes, how can i do this if i want to call after method ends?@escape means that your function can be called after method ends. – user15262125 May 26 '21 at 19:24
  • Exactly. If you want to call the closure after the method ends, add `@escaping` to the parameter. That's the whole thing. – Rob Napier May 26 '21 at 19:24
  • yes but i am checking cpu clock() time but escaping function runs before main calling function, escapingex body starts297900 escapingex closure 298193 escapingex body ends298265 – user15262125 May 26 '21 at 19:26
  • I don't know what `escapingexample` does (you don't give the code for that), but I don't understand why anything here is surprising. Start your question over (edit from the beginning). State clearly what you expect to happen. State clearly why you believe this should happen. State clearly what does happen. State clearly what question you want answered about that. Nothing in your examples above is surprising, but it's very hard to read, so I may be missing something. – Rob Napier May 26 '21 at 19:34
  • that is the same example on the swift site `someFunctionWithEscapingClosure` https://docs.swift.org/swift-book/LanguageGuide/Closures.html#ID546 just checking the clock times about when they start after or before – user15262125 May 26 '21 at 19:37

1 Answers1

2

There is nothing about marking a closure as @escaping that will cause the closure to exist after the function returns. It just allows it. It is legal to store an escaping closure in a property, or to pass it to something that retains it (such as Dispatch.async). It's not legal to do that with a non-escaping closure.

The whole point of marking a parameter as escaping is to warn the caller and the compiler that the closure may outlive this function call. That impacts what the programmer should expect and what kinds of optimizations the compiler can safely perform.

If you convert a non-escaping closure parameter to an otherwise-identical escaping parameter, you should expect no behavioral changes at all.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610