Why specify [unowned self] in blocks where you depend on self being there?
"The Language Guide claims you should use unowned if the closure and containing object reference each other and will be destroyed at the same time. Presumably that's to avoid the cost of safely nil'ing out a weak reference in an object that's about to dealloc anyway."
http://www.russbishop.net/swift-capture-lists
So [unowned self] makes self an an implicitly unwrapped optional, for the convenience of not unwrapping it yourself, at the risk of a crash if of course it is actually nil.
Why would I ever use unowned self?
unowned
has a marginal performance advantage over weak
because the runtime doesn't have to keep track of the reference to turn it into nil
when the object goes away.
In respect of retain cycles (well, strong reference cycles), neither weak
nor unowned
creates a strong reference (in pre ARC terms, neither increments the retain count) so there is no danger of a reference cycle, in fact, that is why you need to specify weak
or unowned
for self
in closures.
Also, with unowned
you can use the reference as a non optional, so you don't have to put any code in the closure to unwrap it.
I always use weak
unless there is a really good performance reason not to.
NB in your code, I do not think either is necessary because the closure is not escaping i.e. The reference to it taken in the function call foo
does not persist after the end of foo
's scope.
Should l I use [unowned self] for Realm.write()?
If you have a look at the write
method declaration, you will see, that the closure is non escaping. So, you don't need to use neither weak
nor unowned
. It will not lead to retain cycle.
public func write(_ block: (() throws -> Void)) throws {
beginWrite()
do {
try block()
} catch let error {
if isInWriteTransaction { cancelWrite() }
throw error
}
if isInWriteTransaction { try commitWrite() }
}
Shall we always use [unowned self] inside closure in Swift
No, there are definitely times where you would not want to use [unowned self]
. Sometimes you want the closure to capture self in order to make sure that it is still around by the time the closure is called.
Example: Making an asynchronous network request
If you are making an asynchronous network request you do want the closure to retain self
for when the request finishes. That object may have otherwise been deallocated but you still want to be able to handle the request finishing.
When to use unowned self
or weak self
The only time where you really want to use [unowned self]
or [weak self]
is when you would create a strong reference cycle. A strong reference cycle is when there is a loop of ownership where objects end up owning each other (maybe through a third party) and therefore they will never be deallocated because they are both ensuring that each other stick around.
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]
. So if a class owns a closure, and that closure captures a strong reference to that class, then you have a strong reference cycle between the closure and the class. This also includes if the class owns something that owns the closure.
Specifically in the example from the video
In the example on the slide, TempNotifier
owns the closure through the onChange
member variable. If they did not declare self
as unowned
, the closure would also own self
creating a strong reference cycle.
Difference between unowned
and weak
The difference between unowned
and weak
is that weak
is declared as an Optional while unowned
is not. By declaring it weak
you get to handle the case that it might be nil inside the closure at some point. If you try to access an unowned
variable that happens to be nil, it will crash the whole program. So only use unowned
when you are positive that variable will always be around while the closure is around
What is this `[unowned self] in` Swift code doing?
What is the navigationCallback being assigned to?
The stuff in curly braces constitutes an anonymous function. It's like a block in Objective-C.
What is
[unowned self]
?
The stuff in square brackets preceding in
in the anonymous function's capture list. It prevents a retain cycle by bringing self
into the anonymous function unretained. unowned
is like an assign
property policy in Objective-C (non-ARC weak
). In Objective-C you'd typically do the weak-strong dance in order to do something similar.
Capturing self weak or unowned on asynchronous network requests
If you capture self without weak
or unowned
keywords, your view controller will be retained by the closure and will not deallocate before the closure dies. The difference between weak
and unowned
is that weak
is an Optional and requires conditional binding as a safety check. On the other hand, unowned
is not as fail-safe. It assumes that your view controller is still alive and it will crash if it is not. For more information see this answer.
Using method with self inside blocks
It is not safe to do this, even if many people a doing it like this.
You should use the "weakSelf" pattern with blocks when it is justified.
In your example the "weakSelf" pattern is not justified, because self
don't have any strong
reference to your block
. You can use like this :
[_dataProvider doA:^(NSError *error) {
// here you can use self, because you don't have any strong reference to your block
[weakSelf handleError:error];
}];
Use "weakSelf" pattern if you have a strong
reference to your block
( with a property or an instance variable for example) and your are capturing self
inside the block
, example :
@property(strong) void(^)(void) completionBlock;
....
__weak typeof(self) weakSelf = self;
self.completionBlock = ^{
// Don't use "self" here, it will be captured by the block and a retain cycle will be created
// But if we use "weakSelf" here many times, it risques that it will be nil at the end of the block
// You should create an othere strong reference to the "weakSelf"
__strong typeof(self) strongSelf = weakSelf;
// here you use strongSelf ( and not "weakSelf" and especially not "self")
};
Related Topics
How to Resolve Error in Unit Testing When We Have Date Comparison in Codable
How Marquee Text of Label on Swift
Swift: Get 30 Days Before 'Specific Date'
Why There Is a Overflow with Swift Language When Assign a 8 Bits Binary Value to a Var of Int8 Type
Swift Calculate Time for Timers Running in Background
The Right Place to Call .Removeobserver for Nsnotificationcenter = Swift Deinit()
Swift Generics Error: Cannot Convert Value of Type 'Type<T>' to Expected Argument Type 'Type<_>'
Changing Texteditor Background Color in Swiftui for MACos
Swiftui - Show the Data Fetched from Firebase in View
Crash When Running on Device After Second Launch
How to Convert Dispatchtimeinterval to Nstimeinterval (Or Double)
New' Is Unavailable: You Cannot Directly Instantiate an Stpissuingcardpin
Moving Keyboard When Editing Multiple Textfields with Constraints Swift
Swiftui on MACos - Handle Single-Click and Double-Click at the Same Time