0

I want to understand in depth about closures and their mechanism of being allocated and usage. After reading and using them a while I have come up with some questions that are really eating up my head:

Question - 1 How is a closure used as a variable different from a normal variable from memory allocation point of view?

eg: let x:NSString ={}() & let x = NSString()

Question-2 How exactly the memory allocation happens for a block?

Please kindly explain these so as that any readers having similar kind of doubts might be beneficial from it.

**EDIT* The answer to this question by Shadow was to an other direction of this question which has been edited.

G.Abhisek
  • 1,034
  • 11
  • 44
  • Your post is too broad, and some of your questions were already answered here, see for example http://stackoverflow.com/questions/32693150/whats-wrong-here-instance-member-cannot-be-used-on-type – Cristik Aug 26 '16 at 05:05
  • @Cristik I have edited my question. Can you please answer the edited questions? Thanks. – G.Abhisek Aug 26 '16 at 05:37

1 Answers1

1

For stored properties with default values or default closures memory allocates immideatly, before init method called. You can not use self or properties for defining other property by default value.

Closures from your example usually used on this step to define lazy properties; they should be var and marked with lazy keyword:

class myClass {
    let x: NSString? = nil
    let q: NSString? = {return "q"}() //allocates before class init; deallocates imidiatly
    lazy var y: NSString = {
        let z  = self.x
        return z ?? ""
    }()                               //allocates on first property call; deallocates imidiatly
}

Memory for lazy properties will be allocated on first property call. Construction {/*...*/}() means that this closure will be executed just at call moment and will return result of calculation (you can look at this like at unnamed function), not reference to this closure. This is very important moment: you are not retain closure, this closure allocates only for execution moment and deallocates just after return, so you don't need care about strong cycle reference problem.

Other thing - when you saving reference to closure:

class myClass {
    let x: NSString? = nil
    var closure: () -> NSString = {return "q"} //allocates before class init; deallocates on references release
    lazy var lazyClosure: () -> NSString = {
        let z  = self.x
        return z ?? ""
    }                                        //allocates on first property call; deallocates on references release
}

Memory for this closures allocates at same time as in previous case, but they will continue to live until have any references. You can look at closures here like at separate objects. Cycle reference problem can arise here. closure is not capture anything, so there are no problems with it, but lazyClosure capture self. If we will never call lazyClosure there will be no problems, since this closure will never allocates. But if we will call it, it will be allocated, it will capture self, and there will be strong cycle reference: self points to lazyClosure instance, lazyClosure points to self instance. To solve this problem you should make one of references weak, you should use capture list: insert [weak self] in or [unowned self] in in lazyClosure body. [unowned self] in in our case, since if property called, then self is not nil.

lazy var lazyClosure: () -> NSString = {
    [unowned self] in
    let z  = self.x
    return z ?? ""
}
Yury
  • 6,044
  • 3
  • 19
  • 41
  • Thanks for replying but can you please modify your answer and include the difference between memory allocation of block when created and objects? – G.Abhisek Aug 26 '16 at 04:45
  • @G.Abhisek I modified answer and corrected mistake, take a look – Yury Aug 26 '16 at 12:53
  • Sorry for replying late. a small clarification- a)What about the variables that are declared within the scope of the closure itself?How their memory allocation happens? – G.Abhisek Aug 29 '16 at 07:25
  • @G.Abhisek this memory allocation happens like in functions (they are closures in fact). More wide, code inside closure order-dependent, memory for variable allocates just at declaration point, and some parts of code can never be executed (memory for that variables will never be allocated). Memory is release with `return` statement (retained references can continue living of course; when you return reference for object for example). Variables in closures are *not like properties*, for example you can not mark them with `lazy` keyword. Each closure invoking result making its own scope. – Yury Aug 29 '16 at 08:20