173

In my TextViewTableViewCell, I have a variable to keep track of a block and a configure method where the block is passed in and assigned.
Here is my TextViewTableViewCell class:

//
//  TextViewTableViewCell.swift
//

import UIKit

class TextViewTableViewCell: UITableViewCell, UITextViewDelegate {

    @IBOutlet var textView : UITextView

    var onTextViewEditClosure : ((text : String) -> Void)?

    func configure(#text: String?, onTextEdit : ((text : String) -> Void)) {
        onTextViewEditClosure = onTextEdit
        textView.delegate = self
        textView.text = text
    }

    // #pragma mark - Text View Delegate

    func textViewDidEndEditing(textView: UITextView!) {
        if onTextViewEditClosure {
            onTextViewEditClosure!(text: textView.text)
        }
    }
}

When I use the configure method in my cellForRowAtIndexPath method, how do I properly use weak self in the block that I pass in.
Here is what I have without the weak self:

let myCell = tableView.dequeueReusableCellWithIdentifier(textViewCellIdenfitier) as TextViewTableViewCell
myCell.configure(text: body, onTextEdit: {(text: String) in
   // THIS SELF NEEDS TO BE WEAK  
   self.body = text
})
cell = bodyCell

UPDATE: I got the following to work using [weak self]:

let myCell = tableView.dequeueReusableCellWithIdentifier(textViewCellIdenfitier) as TextViewTableViewCell
myCell.configure(text: body, onTextEdit: {[weak self] (text: String) in
        if let strongSelf = self {
             strongSelf.body = text
        }
})
cell = myCell

When I do [unowned self] instead of [weak self] and take out the if statement, the app crashes. Any ideas on how this should work with [unowned self]?

D4ttatraya
  • 3,344
  • 1
  • 28
  • 50
NatashaTheRobot
  • 6,879
  • 4
  • 32
  • 27
  • Could you select an answer below as the correct answer then? Also note that with unowned you wouldn't need to strongify self within your closure. Unowned is better than weak here because the life cycle of your cell and view controller are linked. – ikuramedia Jul 02 '14 at 03:37
  • 1
    I realize that [unowned self] if the better option, but my app crashes when I use it. Would love to see a code sample using it to close out the answer. – NatashaTheRobot Jul 03 '14 at 15:08
  • 1
    From the docs: "Like weak references, an unowned reference does not keep a strong hold on the instance it refers to. Unlike a weak reference, however, an unowned reference is assumed to always have a value. " If your app crashes, it's likely because unowned is being applied to a value that's nil at runtime. – Bill Patterson Oct 01 '14 at 18:56
  • Probably better to advertise a guard statement here than if let binding to strongSelf. Just saying, this is like the perfect candidate :-D – Daniel Galasko Dec 09 '15 at 13:29
  • @NatashaTheRobot, What syntax is [weak self] ?. looks like a message passing in objective C. Can you please add a little bit more about the syntax in the question please. – Vignesh Feb 11 '16 at 16:38
  • Instead of `if let strongSelf = self { strongSelf.body = text }` you should use `self?.body = text`. Shorter, clearer. – KPM Mar 02 '17 at 14:43
  • Or "guard let `self` = self else { return }" if you have a bigger logic and want to avoid nesting. – Ricardo Mar 13 '17 at 10:48
  • Rather to your question you are still creating retain cycle while giving self to you TextView delegate – Darshan Mothreja Aug 24 '17 at 08:57
  • @Ricardo In a situation when I do use ```[weak self] in```, and then ```guard let `self` = self else { return }```, what would happen following the guard statement if the guard test succeeds? Would it be possible for the strong self after the guard statement to point to memory that has been released and thus cause a crash? – daniel Jun 26 '22 at 01:54
  • No, because you are retaining it, that's why it is called strong. A dangling pointer is not possible in that case. – Ricardo Jul 12 '22 at 20:27

11 Answers11

190

If self could be nil in the closure use [weak self].

If self will never be nil in the closure use [unowned self].

If it's crashing when you use [unowned self] I would guess that self is nil at some point in that closure, which is why you had to go with [weak self] instead.

I really liked the whole section from the manual on using strong, weak, and unowned in closures:

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html

Note: I used the term closure instead of block which is the newer Swift term:

Difference between block (Objective C) and closure (Swift) in ios

Cœur
  • 37,241
  • 25
  • 195
  • 267
TenaciousJay
  • 6,750
  • 3
  • 45
  • 48
  • 7
    Apple called blocks "closures" in their very first document for a C language extension. (Blocks or closures are an extension of C at the very first. Only MM is related to Objective-C.) Even I prefer the term "closure", too, because "blocks" in C is related to compound statements very often, it is a kind of wrong in both languages, because it is called a closure even it does not close over an object (variable or constant). – Amin Negm-Awad Mar 19 '15 at 12:41
  • 1
    very nicely answered :) – iDevAmit May 23 '17 at 02:54
  • 2
    I would suggest never using `unowned`. Its not worth the risk of causing your app to crash. – Kyle Redfearn Jul 30 '18 at 14:28
38

**EDITED for Swift 4.2:

As @Koen commented, swift 4.2 allows:

guard let self = self else {
   return // Could not get a strong reference for self :`(
}

// Now self is a strong reference
self.doSomething()

P.S.: Since I am having some up-votes, I would like to recommend the reading about escaping closures.

EDITED: As @tim-vermeulen has commented, Chris Lattner said on Fri Jan 22 19:51:29 CST 2016, this trick should not be used on self, so please don't use it. Check the non escaping closures info and the capture list answer from @gbk.**

For those who use [weak self] in capture list, note that self could be nil, so the first thing I do is check that with a guard statement

guard let `self` = self else {
   return
}
self.doSomething()

If you are wondering what the quote marks are around self is a pro trick to use self inside the closure without needing to change the name to this, weakSelf or whatever.

LightMan
  • 3,517
  • 31
  • 31
  • I prefer to this answer, what a neat solution! – Jagie Aug 14 '16 at 05:08
  • 2
    ` self ` is a sample of shadowing, an article about it can be found here http://arsenkin.com/swift-closure-without-ugly-strongSelf.html – Cullen SUN Oct 05 '16 at 16:27
  • Nice! Awesome find! – Ralf Hundewadt Nov 02 '16 at 16:08
  • Nice! but '@noescape' doesnt work for typealiased closures. So have to use 'self' thing as u suggested. – infiniteLoop Nov 25 '16 at 18:10
  • 2
    I tend to call the local "self" "strongSelf" to make sure it's not confused with the default self and is easier to spot whether you've guarded for a strong self reference. – Justin Stanley Dec 13 '16 at 20:15
  • 1
    This should not be used, as it is a compiler bug: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160118/007425.html – Tim Vermeulen Feb 27 '17 at 15:20
  • 1
    I think the comment by Chris Lattner in above link is just about not naming the variable as `self` (in backticks). Name it something else such as nonOptionalSelf and it will be fine. – OutOnAWeekend Apr 09 '17 at 20:12
  • 1
    Nowadays (swift 4.2) `{ [weak self] in guard let self = self else { return }` can be used without backticks, and is actually supported: https://github.com/apple/swift-evolution/blob/master/proposals/0079-upgrade-self-from-weak-to-strong.md#proposed-solution – Koen. Mar 02 '19 at 09:36
  • @Koen. In that case, doesn't the closure continue to run until it comes to an end, at which time strong self releases the object. Is there a way to use a weak self in the closure so that at any time during the execution process of the closure the object is released by all other strong references, the weak self becomes nil and the closure stops executing in the middle of processing? – daniel Jan 27 '22 at 02:03
  • @Koen. When I use weak self as in this code: interactiveQueue.async { [weak self] in self?.intNumber += 1 }, sometimes I get an error saying the optional self needs to be unwrapped by using a ! – daniel Jan 27 '22 at 02:09
  • I noticed I get that error when using a for-in loop, such as { [weak self] in for item in self?.arrayOfItems }. – daniel Jan 27 '22 at 02:14
36

EDIT: Reference to an updated solution by LightMan

See LightMan's solution. Until now I was using:

input.action = { [weak self] value in
    guard let this = self else { return }
    this.someCall(value) // 'this' isn't nil
}

Or:

input.action = { [weak self] value in
    self?.someCall(value) // call is done if self isn't nil
}

Usually you don't need to specify the parameter type if it's inferred.

You can omit the parameter altogether if there is none or if you refer to it as $0 in the closure:

input.action = { [weak self] in
    self?.someCall($0) // call is done if self isn't nil
}

Just for completeness; if you're passing the closure to a function and the parameter is not @escaping, you don't need a weak self:

[1,2,3,4,5].forEach { self.someCall($0) }
Ferran Maylinch
  • 10,919
  • 16
  • 85
  • 100
34

Put [unowned self] before (text: String)... in your closure. This is called a capture list and places ownership instructions on symbols captured in the closure.

ikuramedia
  • 6,038
  • 3
  • 28
  • 31
  • 2
    Thanks for naming it, I wanted to know that! – rob5408 May 15 '15 at 01:14
  • 4
    I don't think this answer is useful. [unowned self] will crash if self becomes nil during the execution of closure – Yunus Nedim Mehel Feb 25 '16 at 12:49
  • 3
    there is **absolutely no reason** to use unowned, other than (1) in *extremely* unusual situations, for performance (this is utterly irrelevant here and in 99.999% of programming) and (2) as a style-enforcement matter. The statement "You should always use weak, never unowned" is very reasonable. – Fattie Feb 01 '17 at 15:58
28

Use Capture list

Defining a Capture List

Each item in a capture list is a pairing of the weak or unowned keyword with a reference to a class instance (such as self) or a variable initialized with some value (such as delegate = self.delegate!). These pairings are written within a pair of square braces, separated by commas.

Place the capture list before a closure’s parameter list and return type if they are provided:

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

If a closure does not specify a parameter list or return type because they can be inferred from context, place the capture list at the very start of the closure, followed by the in keyword:

lazy var someClosure: Void -> String = {
    [unowned self, weak delegate = self.delegate!] in
    // closure body goes here
}

additional explanations

Community
  • 1
  • 1
hbk
  • 10,908
  • 11
  • 91
  • 124
  • 3
    You used unowned for "self" which means you know for sure "self" wont be nil when you access it. Then you used force unwrap on "self.delegate" (which also means you know for sure it wont be nil) to assign it to a weak var. If you know for sure that "self.delegate" wont be nil, why not using unowned on the "delegate" instead of weak? – RawKnee Jun 29 '17 at 10:45
15

As of swift 4.2 we can do:

_ = { [weak self] value in
    guard let self = self else { return }
    print(self) // will never be nil
}()
Sentry.co
  • 5,355
  • 43
  • 38
  • Others have similar solutions, but "this" is C++ IMHO. "strongSelf" is a Apple convention and anyone who glances at your code will know whats going on. – David H Jul 06 '18 at 18:22
  • 1
    @ David H IMO the phrase `strongSelf` explicitly explains the variables meaning/sideeffect which is nice if the code is of a more lengthy nature. appreciate your opinion though, did not know c++ used such phrasing. – Sentry.co Jul 08 '18 at 12:08
  • 3
    As of Swift 4.2 you can use `guard let self = self else { return }` to unwrap `[weak self]` : https://github.com/apple/swift-evolution/blob/master/proposals/0079-upgrade-self-from-weak-to-strong.md – Amer Hukic Sep 13 '18 at 21:42
  • @AmerHukic . – Sentry.co Sep 17 '18 at 08:49
8

Swift 4.2

let closure = { [weak self] (_ parameter:Int) in
    guard let self = self else { return }

    self.method(parameter)
}

https://github.com/apple/swift-evolution/blob/master/proposals/0079-upgrade-self-from-weak-to-strong.md

Alan McCosh
  • 141
  • 2
  • 2
3

You can use [weak self] or [unowned self] in the capture list prior to your parameters of the block. The capture list is optional syntax.

[unowned self] works good here because the cell will never be nil. Otherwise you can use [weak self]

zord
  • 4,538
  • 2
  • 25
  • 30
Rufus
  • 2,058
  • 2
  • 16
  • 10
0

If you are crashing than you probably need [weak self]

My guess is that the block you are creating is somehow still wired up.

Create a prepareForReuse and try clearing the onTextViewEditClosure block inside that.

func prepareForResuse() {
   onTextViewEditClosure = nil
   textView.delegate = nil
}

See if that prevents the crash. (It's just a guess).

Michael Gray
  • 611
  • 1
  • 5
  • 13
0

[Closure and strong reference cycles]

As you know Swift's closure can capture the instance. It means that you are able to use self inside a closure. Especially escaping closure[About] can create a strong reference cycle[About]. By the way you have to explicitly use self inside escaping closure.

Swift closure has Capture List feature which allows you to avoid such situation and break a reference cycle because do not have a strong reference to captured instance. Capture List element is a pair of weak/unowned and a reference to class or variable.

For example

class A {
    private var completionHandler: (() -> Void)!
    private var completionHandler2: ((String) -> Bool)!
    
    func nonescapingClosure(completionHandler: () -> Void) {
        print("Hello World")
    }
    
    func escapingClosure(completionHandler: @escaping () -> Void) {
        self.completionHandler = completionHandler
    }
    
    func escapingClosureWithPArameter(completionHandler: @escaping (String) -> Bool) {
        self.completionHandler2 = completionHandler
    }
}

class B {
    var variable = "Var"
    
    func foo() {
        let a = A()
        
        //nonescapingClosure
        a.nonescapingClosure {
            variable = "nonescapingClosure"
        }
        
        //escapingClosure
        //strong reference cycle
        a.escapingClosure {
            self.variable = "escapingClosure"
        }
        
        //Capture List - [weak self]
        a.escapingClosure {[weak self] in
            self?.variable = "escapingClosure"
        }
        
        //Capture List - [unowned self]
        a.escapingClosure {[unowned self] in
            self.variable = "escapingClosure"
        }
        
        //escapingClosureWithPArameter
        a.escapingClosureWithPArameter { [weak self] (str) -> Bool in
            self?.variable = "escapingClosureWithPArameter"
            return true
        }
    }
}
  • weak - more preferable, use it when it is possible
  • unowned - use it when you are sure that lifetime of instance owner is bigger than closure

[weak vs unowned]

yoAlex5
  • 29,217
  • 8
  • 193
  • 205
0

From Swift 5.3, you do not have to unwrap self in closure if you pass [self] before in in closure.

Refer someFunctionWithEscapingClosure { [self] in x = 100 } in this swift doc

Deepak Thakur
  • 3,453
  • 2
  • 37
  • 65