I'm aware of the fact that closure can create retain cycles if it is assigned to a property of a class and instance properties of the class are used inside of the closure. But
1) what about the closure is not assigned to the class property but passed as parameter to a singleton's class method ?
2) How the memory is managed in this case ?
In a method of my controller (UIViewController) I have something like:
MySingleton.classMethod(parameters ..., completion: { () -> Void in
/**
doing stuff here
*/
})
If You are not assigning the closure to a property, but just passing it to a function You need to consider if the closure will be escaping or noescape. In Swift 3 by default all closures passed to functions are non-escaping.
Here is a little bit more info on the matter:
"noescape" - the passed closure is invoked before the return of the function
"escaping" - If a closure is passed as an argument to a function and it is invoked after the function returns, the closure is escaping.
Simple explanation : We need to mark closure as escaping when we pass it to a function and the closure will be called after this function returns.
General rule is when the closure is escaping You need to use capture list to prevent retain cycles.
Example
let closure = { [weak someVariable] (name: Type) -> Void in
....
// code
}
Additional info:
One weird thing is that optional closures are treated as escaping. And when we explicitly add escaping keyword, there is a compile error -escaping attribute only applies to function types.
See the below links for more info.
https://bugs.swift.org/browse/SR-2053
https://stackoverflow.com/a/39619298/5388473
https://stackoverflow.com/a/39846519/5388473
Update
The idea of using weak or unowned in the capture lists of escaping closures is that essentially We don't know what will happen with the passed escaping closure, it may be called sometime later from another function or it may be stored in some object, which may lead to a strong retain cycle.
weak vs unowned vs strong capture
For more detailed information check Apple ARC docs.
From Apple docs:
Swift provides two ways to resolve strong reference cycles when you
work with properties of class type: weak references and unowned
references.
Weak and unowned references enable one instance in a reference cycle
to refer to the other instance without keeping a strong hold on it.
The instances can then refer to each other without creating a strong
reference cycle.
Use a weak reference when the other instance has a shorter
lifetime—that is, when the other instance can be deallocated first.
Use an unowned reference when the other instance has the same lifetime
or a longer lifetime.
Keep in mind that the weak approach will add a boiler plate to the code and will be a little bit more slow, because ARC will add code for setting the weak variables to nil on their deallocation. It is a good practice to follow the rules stated above, when choosing weak or unowned.
Related
I have a strongly referenced model in my view controller that has a function listenToQueue which "listens" to my Firebase database for real time updates. Whenever an update occurs, it passes back an object to my view controller, which then calls a function. Here is my code:
eventModel.listenToQueue { [weak self] queuer in
self?.queuerDidChange(queuer: queuer)
}
This works. However, originally my code looked like this:
eventModel.listenToQueue(updateHandler: queuerDidChange)
This caused a retain cycle between the model and the view controller. However, that code looks cleaner, so I'm wondering if there's a way to pass the queuerDidChange function via a weak reference to self? I tried this already, but the retain cycle is still there:
weak var weakSelf = self
eventModel.listenToQueue(updateHandler: weakSelf?.queuerDidChange)
Is it possible to do what I want, or shall I just stick to the code I've got?
weak var weakSelf = self
eventModel.listenToQueue(updateHandler: weakSelf?.queuerDidChange)
Above code is the same code as:
eventModel.listenToQueue(updateHandler: queuerDidChange)
Because you declare weakSelf and use it immediately. weakSelf?.queuerDidChange has no relation to weakSelf, instead it already contains reference to self itself. I assume queuerDidChange member function. So the only way to avoid retain cycle is what you call the dirty way.
eventModel.listenToQueue { [weak self] queuer in
self?.queuerDidChange(queuer: queuer)
}
I noticed this in one of my apps. I like the look of passing in the method itself, but I also had to use the weak reference technique you mentioned.
This makes sense, I think, because method implementations are held on the class itself, and self is bound to that implementation when classes are instantiated. Therefore a method will always have a strong reference to self.
And in Swift, function parameters are strongly referenced. I don’t think there’s a way to pass any parameter using a weak reference.
Need clarification on blocks and closure.
How blocks will retain the object? or why we need to use only weak inside block? What will happen if we don't follow this? Or please give some clarity on block.
The below one os for closure.
I have written some code like this. favouriteButton is a property of self.
favouriteButton.hidden = false
dispatch_async(dispatch_get_main_queue(), {
self._collectionView.reloadData()
})
It didn't gave any error. So I thought of doing UI in main thread. So I moved the code to disable hidden inside block like below.
dispatch_async(dispatch_get_main_queue(), {
favouriteButton.hidden = false
self._collectionView.reloadData()
})
It shows an error like
reference to property 'favouriteButton' in closure requires explicit
'self'
dispatch_async(dispatch_get_main_queue(), {
self.favouriteButton.hidden = false
self._collectionView.reloadData()
})
Could any one please explain how to use closure/block effectively.
Does the blocks and closures work in the same way?
In Swift (and Objective-C), a block is a closure. The term closure refers to an individually-executable block of code that captures the values of variables in the enclosing scope. In the case of Swift, the enclosing scope is usually a function, and only variables used within the block are captured.
The reason you need to preface class-level references (properties and function calls) with self. is to make explicit the capturing of self. Doing so allows you to specify how self (or any other object reference) is captured: strong (default) or weak.
There are two reasons to be careful with retaining objects (keeping strong references) within a block.
The most common concern is creating a retain cycle. This is where the block retains a strong reference to an object, which in turn has a strong reference to the block. Until one of the references is explicitly broken, neither the block, nor the object, will be released. (Releasing a block simply cleans up the captured variables. The executable code remains.)
A strong reference to an object within a block can keep the object alive longer than intended. For example, if a block keeps a reference to a view controller that is popped off a navigation stack, you likely don't want that block to act on the view controller when its executed. This can be avoided by capturing a weak reference to the view controller. This allows the view controller to be deallocated when it's popped, and the block becomes a no-op.
I just read the ARC section in the Swift book and a few other related posts concerning weak and unowned references.
After my readings, I do have a clear understanding on what they are and in what situations each of them are to be used (see also this SO post which gives a great explanation of this).
However, I fail to understand why Apple even came up with these two solutions? Essentially, from a MM perspective, both come down to not creating a strong reference to the referred object (i.e. not increasing its retainCount). So, why even bother and provide two MM primitives here?
Now, developers need to understand when to use which of the two, and Apple did a great job in explaining the different scenarios, but they didn't say why. Wouldn't it have been simpler to e.g. only provide weak so that developers don't need to dig into the docs and understand the different use cases?
I guess, another way to phrase the question is, why at all should we use unowned, except for Apple telling us so? At least from a MM standpoint, this wouldn't make a difference and using weak where according to the docs we should use unowned wouldn't create a memory leak?!
The difference is in the optionality of variables. Like Apple says in the Unowned References section of the link you provided:
Unlike a weak reference, however, an unowned reference is assumed to
always have a value. Because of this, an unowned reference is always
defined as a nonoptional type.
The usage of this is more visible in a closure block. Here you do not have to use ? operator or get a reference on the object if you use it inside the closure.
Instead of writing this:
UIView.animateWithDuration(0.2) {
[weak self]
() -> Void in
self?.view.layoutIfNeeded()
}
However, if you can be sure that the reference to self will not be released before the animation and you can simply write unowned and do not have to use the ? operator or unwrap it with an if let statement:
UIView.animateWithDuration(0.2) {
[unowned self]
() -> Void in
self.view.layoutIfNeeded()
}
#Kádi's answer about weak variables being optional is correct, but incomplete.
Weak and unowned have a difference in meaning outside of Swift's Optional semantics. A weak reference is more accurately named an auto-zeroing weak reference. The system knows about an object stored in a weak variable, and when the object is deallocated, goes to the extra work to zero out the value. As a consequence of that, weak variables are optionals in Swift.
Unowned pointers are not memory managed at all. They are a raw memory pointer that can take any value. (They can still be typed to point to a particular type of structure, so they aren't always "raw" in the way a C void pointer is raw.) Unowned pointers are useful for pointing to malloc'ed memory, pointer arithmetic, and the like. Declaring a pointer type as unowned basically tells the compiler "Don't worry about it. I know what I'm doing." The burden is then on you to make sure the pointer is always valid, before you try to dereference it, and also manage the memory behind the pointer yourself.
I have see many blocks use "self.xxx" in a block, then how can I make sure the "self" is the instance I want?
Example:
I am in instance A, whose delegate is B.
And then I call [A.delegate dispatchBlockTest]
The dispatchBlockTest in instance B is like this:
dispatch_async(dispatch_get_main_queue(DISPATCH_UEUE_PRIORITY_DEFAULT, 0),^{
[self printClassName];
});
});
Then, the "self" in the block is definitely B? not A?
Any sort of help is appreciated, thanks.
Fonix's comment is right on. For more information, you can check out this page from the official Apple docs. Specifically take a look at the "Blocks Can Capture Values from the Enclosing Scope" section. The meaning of a variable in a block is always "captured" when the block is declared, so local variables, properties, and references to self are all based on the scope of where the block is declared (in your case, the scope in class A) and NOT based on where the block is called (in your case, class B).
On a side note, one subtle thing it's worth knowing about using self with blocks is that you can create a type of memory leak known as a strong reference cycle or a retain cycle (Check out the section on weak properties here for an explanation). In general, it's good practice to always use a weak reference to self in blocks (Apple has a good example here). Most of the time, using self in a block won't create a strong reference cycle, but if you always use a weak reference to self in a block, you don't have to think about whether or not you risk a reference cycle.
I have a question regarding memory deallocation and blocks/closures.
Following is the Swift method
self!.dismissViewControllerAnimated(false, completion: {
println(self);
})
Or the objective C method
[self dismissViewControllerAnimated:NO completion:^{
NSLog("%#",self);
}];
I would really appreciate if anyone could explain when in the above method self would be deallocated . Is it after the completion block is run or before that? I understand its taken care by ARC but I would like to know if self gets release message in the completion block or after that. Hence, if I do some minor clean up in the completion block (accessing self), is that safe/acceptable or not?
There are really two separate questions to understand the answer completely:
1. When Are Variables Referenced Inside of Closures Released?
You can think of a closures as just another type (in Swift they really are). Every closure creates a strong ownership over the variables referenced inside of it, including self. This ensures that you never reference a variable that has been deallocated. Just like in any other object, when the closure gets deallocated, it releases its ownership over all of its variables.
If the closure is the only thing with a strong reference to that a variable, the variable will be dealloced when the closure is dealloced.
So in short, variables stay in memory as long as the closure is still in memory.
2. When Are Closures Deallocated?
Now the second part of this that is important to understand, is when does a closure get dealloced. You could store a closure in a variable:
func myMethod() {
var myClosure = {
println(self)
}
myClosure()
}
In this case, the closure has a strong reference from its variable myClosure and the closure has a strong reference to self. As soon as myClosure goes out of scope, i.e. when myMethod exits, it will be dealloced. When that happens, self will be released.
You may also have a situation, like in your question, where you are passing a closure into another method. In this case, the method you are passing the closure into is capturing a strong reference to your closure. When that method exits, it will release your closure, the closure will be deallocated, and it will release all variables captured inside it.
The Exception
Sometimes it is necessary to define a closure that does not take ownership over a variable. You would do this to avoid circular references. You can read more in Apple's documentation on what a circular reference is and how to prevent them here. However, it is important to realize that unless you put in explicit effort (and code), closures will always capture strong references to variables referenced inside of it.
In Swift, while developing/debugging and trying to understand the timing of operations, you can add the following to your View Controllers (or any class), to track if or when the instance is a about to deallocated.
Although that won't help you detect 'strong reference cycles' described here:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html
deinit {
println(__FUNCTION__, "\(self)")
}