Is 'self' retained instead of member-function?


(Daniel Tartaglia) #1

In the code below, I’m confused as to wether ‘self’ is owned, unowned or retained inside the ‘bar()’ function. I was assuming that it would always be retained, but I am wondering if that’s correct… Especially the ‘unownedThunk’ example… I don’t recall anything in the Swift book explicitly answering this question.

class Foo {

    init() {
        ownedThunk = {
            self.bar()
        }
        unownedThunk = { [unowned self] in
            self.bar()
        }
        weakThunk = { [weak self] in
            self?.bar()
        }
    }

    func bar() {
        // is 'self' owned/unowned/weak? here?
    }

    private var ownedThunk: () -> Void = { }
    private var unownedThunk: () -> Void = { }
    private var weakThunk: () -> Void = { }

}


(Joe Groff) #2

Yeah, 'self' is always a strong reference if it isn't overridden by a capture list declaration, as are all arguments.

-Joe

···

On Feb 10, 2016, at 12:33 PM, Daniel Tartaglia via swift-users <swift-users@swift.org> wrote:

In the code below, I’m confused as to wether ‘self’ is owned, unowned or retained inside the ‘bar()’ function. I was assuming that it would always be retained, but I am wondering if that’s correct… Especially the ‘unownedThunk’ example… I don’t recall anything in the Swift book explicitly answering this question.

class Foo {

    init() {
        ownedThunk = {
            self.bar()
        }
        unownedThunk = { [unowned self] in
            self.bar()
        }
        weakThunk = { [weak self] in
            self?.bar()
        }
    }

    func bar() {
        // is 'self' owned/unowned/weak? here?
    }

    private var ownedThunk: () -> Void = { }
    private var unownedThunk: () -> Void = { }
    private var weakThunk: () -> Void = { }

}

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(bishal ghimire) #3

Swift book has very good examples and well documented on it -

“myFunction { print(self.title) } // strong capture
myFunction { [weak self] in print(self!.title) } // weak capture
myFunction { [unowned self] in print(self.title) } // unowned capture”

Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2.2 Prerelease).” iBooks. https://itun.es/us/k5SW7.l

Another example

“lazy var someClosure: (Int, String) -> String = {
    [unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
    // closure body goes here
}”

“Weak and Unowned References
Define a capture in a closure as an unowned reference when the closure and the instance it captures will always refer to each other, and will always be deallocated at the same time.

Conversely, define a capture as a weak reference when the captured reference may become nil at some point in the future. Weak references are always of an optional type, and automatically become nil when the instance they reference is deallocated. This enables you to check for their existence within the closure’s body.

NOTE

If the captured reference will never become nil, it should always be captured as an unowned reference, rather than a weak reference.

An unowned reference is the appropriate capture method to use to resolve the strong reference cycle in the HTMLElement example from earlier. Here’s how you write the HTMLElement class to avoid the cycle:

class HTMLElement {
    
    let name: String
    let text: String?
    
    lazy var asHTML: Void -> String = {
        [unowned self] in
        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")
    }
    
}
This implementation of HTMLElement is identical to the ”
“ } else {
            return "<\(self.name) />"
        }
    }
    
    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }
    
    deinit {
        print("\(name) is being deinitialized")
    }
    
}
This implementation of HTMLElement is identical to the previous implementation, apart from the addition of a capture list within the asHTML closure. In this case, the capture list is [unowned self], which means “capture self as an unowned reference rather than a strong reference”.

You can create and print an HTMLElement instance as before:

var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
// Prints "<p>hello, world</p>"
Here’s how the references look with the capture list in place:

“This time, the capture of self by the closure is an unowned reference, and does not keep a strong hold on the HTMLElement instance it has captured. If you set the strong reference from the paragraph variable to nil, the HTMLElement instance is deallocated, as can be seen from the printing of its deinitializer message in the example below:

paragraph = nil
// Prints "p is being deinitialized"
For more information about capture lists, see Capture Lists.”

Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2.2 Prerelease).” iBooks. https://itun.es/us/k5SW7.l

Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2.2 Prerelease).” iBooks. https://itun.es/us/k5SW7.l

···

Yeah, 'self' is always a strong reference if it isn't overridden by a capture list declaration, as are all arguments.

-Joe

> On Feb 10, 2016, at 12:33 PM, Daniel Tartaglia via swift-users<swift-users at swift.org>wrote:
>
> In the code below, I’m confused as to wether ‘self’ is owned, unowned or retained inside the ‘bar()’ function. I was assuming that it would always be retained, but I am wondering if that’s correct… Especially the ‘unownedThunk’ example… I don’t recall anything in the Swift book explicitly answering this question.
>
>
> class Foo {
>
> init() {
> ownedThunk = {
> self.bar()
> }
> unownedThunk = { [unowned self] in
> self.bar()
> }
> weakThunk = { [weak self] in
> self?.bar()
> }
> }
>
> func bar() {
> // is 'self' owned/unowned/weak? here?
> }
>
> private var ownedThunk: () ->Void = { }
> private var unownedThunk: () ->Void = { }
> private var weakThunk: () ->Void = { }
>
> }
>
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users