2
class HTMLElement {

    let name : String
    let text: String?

    //Declaring a lazy variable that has a strong reference to this closure
    lazy var asHTML: Void -> String = {
        //Optional binding here
        if let text = self.text {
             return "<\(self.name)>\(text)<\(self.name)>"
        } else {
            return "<\(self.name) >"
        }
    }

    init(name: String, text: String? = nil){
        self.name = name
        self.text = text
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

My Question is: Why is the closure declared Lazy, I know it has something to do with self not being known in the closure, but isn't that the same case for the init method where self hasn't been created?

Secondly,Where exactly is the strong reference cycle in this code example, is it self that strongly references to asHTML, if so where is the second part of the strong referencing that causes the cycle?

Third, Why is the constant text property an optional when constants cannot change value(from nil to a value and back to nil)?

Lastly, What does it mean to have the parameter text: String? = nil in the init method when the init method is used to accept parameters sent by the user?

Sorry for this long question, I'm just confused on the closure strong reference cycle....although I do understand strong reference cycles between class properties and class instances.

Alexey Pichukov
  • 3,377
  • 2
  • 19
  • 22
Ali
  • 505
  • 4
  • 12

1 Answers1

1

1

lazy is used for attributes that are only created when called upon. So before you call myClass.myLazyAttribute it will not take up any space. This also means that it will init after the class has initialised, which can be very useful.

In this case lazy is used to get access to self, like you stated, because self is not available until the instance has been initialised.

2

The apple doc from where code is.

Closures capture the values used in them. In this case it captures self. It does not create a Strong Reference Cycle between class A and class B, but between itself and a closure. It makes a lot more sense if you imagine that the operation inside the closure takes a very long time. During the execution something else has happened and you want to deinit the instance. But the closure has captured self and it will keep the instance alive until it is done.

By using [unowned self] in you can again deinit the instance while the closure is running. Although this will crash your app.

good info on this specific use : link

In the specific case of a closure, you just need to realize that any variable that is referenced inside of it, gets "owned" by the closure. As long as the closure is around, those objects are guaranteed to be around. The only way to stop that ownership, is to do the [unowned self] or [weak self].

What a Strong Reference Cycle in essence is:

  • you have an instance of a class
  • the instance has a reference count higher than 0
  • there is no longer a reference to the instance available to your program.

Or even shorter: the reference count of the instance is higher than the number of accessible references.

In this case the reference count of self goes up by 1 because it is captured by the closure. We can not access that reference because we can not say something like: closure.selfAttribute, so we can not set that to nil. Only when the closure is finished will the reference count go down by 1 again.

3

It is an optional constant, but it's initial value is set in the init method of the class. So it can receive a value in the init method, but it will be immutable. This is called a late init.

4

This is a function parameter with a default value.

func someFunction(myParamWithDefaultValue : Int = 10) {
    print(myParamWithDefaultValue)
}

someFunction() // 10
someFunction(5) // 5
Community
  • 1
  • 1
R Menke
  • 8,183
  • 4
  • 35
  • 63
  • 1
    Note that not just `weak` but also `unowned` isn't a strong reference – Kametrixom Nov 19 '15 at 06:31
  • ok now I have a question, If I create an instance of the `HTMLElement` class, the documentation says that there will be a strong reference cycle, I understand half of what they mean.......The closure uses self.name and self.text which "captures" self and makes a strong reference to instances of the `HTMLElement` class.....now how is there a strong reference FROM the instance back to the closure?? – Ali Nov 19 '15 at 06:33
  • @Ali then I would need to know how the other side looks like. Also where is this code from. You mention documentation, so is this a tutorial, or a framework? – R Menke Nov 19 '15 at 06:36
  • This is straight from the Apple documentation: {\[https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID48] – Ali Nov 19 '15 at 06:40
  • All the way down to the Closure strong reference cycle example – Ali Nov 19 '15 at 06:41
  • @Ali updated. The apple doc example is stupid. They explain the technical side but not the practical side. It makes more sense if you can imagine when and how this might be a problem. – R Menke Nov 19 '15 at 06:50
  • ok so I shouldn't worry about this too much, I'm a beginning swift programmer and plan to build iOS apps which has gotten me overwhelmed with all the info I have to learn, so you think I should just get the basic info and drive right in? – Ali Nov 19 '15 at 06:52
  • The thing is I'm not understanding how an instance could point to the closure and strongly reference it?? I know how the closure is currently pointing to the instance because it has captured `self` which is aka an instance of the class..... – Ali Nov 19 '15 at 06:54
  • @Ali check this article out: http://krakendev.io/blog/weak-and-unowned-references-in-swift, it helped me understand the semantics. – barndog Nov 19 '15 at 12:31
  • @RMenke, "Only when the closure is finished will the reference count go down by 1 again." Does it mean that as soon as the closure was executed, both self and the closure will get deallocated? You can imagine a uialertaction with a closure capturing self. – Fawkes Oct 04 '16 at 11:16
  • 1
    @Fawkes sorry for the late reply. If you capture `self` in a closure and this closure is a long operation (network request) and there are no longer any other reference to `self` when the operation is finished `self` will get deallocated. – R Menke Oct 09 '16 at 09:37