I have created a class called VerifyObject, that contains a function with a signature like that
typealias handlerCodeID = (String) ->Void
class func checkPause(withID:String?,
runOnPause: handlerCodeID?)
When I run that, I need to pass a weak self reference to inside the closure, using
VerifyObject.checkPause(withID: "abcde",
runOnPause: {[weak self] (objectID) in
self.doSomething()
})
Xcode complains that the self in doSomething must be unwrapped to
self!.doSomething()
why? Does not make sense.
self is inside a completion handler so it might not be there anymore once the callback gets fired (it might be a network operation or something that take some take and won't return a result for several seconds if not more).
You could check if self exists before accessing it instead of unwrapping:
VerifyObject.checkPause(withID: "abcde",
runOnPause: {[weak self] (objectID) in
guard let self = self else { return }
self.doSomething()
})
Or even shorter only doSomething if self is not nil:
VerifyObject.checkPause(withID: "abcde",
runOnPause: {[weak self] (objectID) in
self?.doSomething()
})
Or if you're absolutely sure that self will exist:
VerifyObject.checkPause(withID: "abcde",
runOnPause: {(objectID) in
self.doSomething()
})
Just be mindful that this last one might cause reain cicles in case where the 2 objects have a strong reference to each other and they will never get deallocated.
While the accepted answer explains how you handle weak self according to different scenarios, I feel like it fails to properly explain why you gotta unwrap weak references and why use weak references in the first place. Understanding this chain will automatically make you understand why you have to unwrap a weak self
Closures are awesome, if you handle them properly
The usual major caveat(that beginners often tend to overlook) with closures is that they capture the class they are declared on, IF you use something that belongs to the class inside the closure.
I'll explain the 'capturing' process:
1) The closures that you declare as a property for your class are escaping closures.
2) To explain what escaping closures are, they don't deallocate with the block they are declared at. They instead escape and outlive the block to provide you callback.
(Also, you might have noticed that the compiler asks you to specify #escaping exquisitely when you pass a closure as a function parameter to provide completion blocks, and this is exactly why it asks you to)
3) Hence, using something that belongs to the class(such as a property) inside an escaping closure allows the closure to capture(retain in memory) the whole class to provide you callback, and this leads to retain cycles
Here's an example: (The same one from the link that I'll share)
Say you have this class:
class ListViewController: UITableViewController {
private let viewModel: ListViewModel
init(viewModel: ListViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
viewModel.observeNumberOfItemsChanged {// Assume this to be some closure that I have in my viewModel
// This will cause a retain cycle, since our view controller
// retains its view model, which in turn retains the view
// controller by capturing it in an escaping closure.
self.tableView.reloadData()
}
}
}
All these happen because the closure holds a strong reference to your class. To break this strong reference, you use weak self in your callback. The weak keyword in a nutshell deallocates the class object if it remains unused for a considerable amount of time and helps break retain cycles
And now, to your question: (You might know the answer already if you made it this far :-))
You have to unwrap weak self because it might no longer be in memory, simple as that!
Finally, here's the link that I was talking about: Capturing objects in Swift closures
NOTE:
In certain cases, you can almost be pretty sure that the captured object will remain in memory by the time you receive callbacks, but want self to be deallocated after that. In those cases, you can use unowned self instead of weak self to break free from the unwrapping hassle. This is almost the same as unwrapping an optional and hence will crash if self is deallocated
using [weak self] or [unowned self], creates a weak reference to avoid memory leaks u should use both of these when using clousre,
now I u just want to avoid "?" optionals
use unowned reference with your self in the clousre
Related
I'm learning about weak vs strong and still don't fully grasp it. How can I declare weak response in the following function so I don't have a retained cycle?
AF.request(url, method: .get).validate().responseData { [weak self] response in
guard let data = response.data else {
completionHandler(.failure(.apiFailed))
return
}
do {
let decodedData = try JSONDecoder().decode(T.self, from: data)
DispatchQueue.main.async {
completionHandler(.success(decodedData))
}
} catch {
completionHandler(.failure(.corruptedData))
return
}
}
Right now I have an xcode warning saying:
Variable 'self' was written to, but never read
How can I read it using weak?
A retain cycle can only happen when an object ends up owning itself through a series of strong relationships, usually through one or more objects in a chain. For instance, if an object A has an owning relationship to an object B, and object B has an owning relationship to object A, then A ends up with an owning relationship to itself, which can prevent it from being deallocated. Breaking this cycle requires one of these objects to change its ownership to a non-owning relationship (weak, or unowned). (This can also happen if A stores a strong reference directly to itself, or if the chain goes A -> B -> C -> D -> A, or any number of other configurations.)
In the context of callbacks like this, the risk you run into with retain cycles is that if object A stores a closure which has a strong (the implicit default) reference to A somewhere inside of it, it cyclicly refers to itself.
However: this only happens if the closure actually has a reason to maintain a strong reference to A in the first place. Your closure, for instance, never refers to self inside of it, so would have no reason to maintain a reference to self, strong or otherwise. Closures only maintain references (or "close over", hence "closure") to the things used inside of them — and self is not.
Hence the warning: you are never "reading" (i.e. accessing) self anywhere inside of the closure, so the [weak self] is unnecessary altogether.
Consider the following piece of code:
class myDropBounceAndRollBehavior: UIDynamicBehavior {
let v = UIView()
init(view v: UIView) {
self.v = v
super.init()
}
override func willMove(to anim: UIDynamicAnimator?) {
guard let anim = anim else {return}
let sup = self.v.superview!
let grav = UIGravityBehavior()
grav.action = { [unowned self] in
let items = anim.items(in: sup.bounds) as! [UIView]
if items.index(of: self.v) == nil {
anim.removeBehavior(self)
self.v.removeFromSuperview()
}
}
self.addChildBehavior(grav)
grav.addItem(self.v)
}
}
Here we have a class with a function willMove(anim:) that has closure that references itself, creating a retain cycle. To resolve this issue, Matt sets self to unowned self to break the cycle.
His next paragraph says this:
There's a potential (and rather elaborate) retain cycle here:
self.addChildBehavior(grav) causes a persistent reference to grav,
grav has a persistent reference to grav.action and the anonymous
function assigned to grav.action refers to self. To break the
cycle, I declared the reference to self as unowned in the
anonymous function's capture list
With that extract from the book, I drawn up reference graph for the situation below,
So, when the function willMove(anim:) is triggered, the function call self.addChildBehavior(grav) that references grav will be created, creating a strong reference to the grav reference instance. but since function willMove(anim:) lives on the main thread, the function self.addChildBehavior(grav) has to finish before releasing the heap memory for willMove(anim:), therefore self.addChildBehavior(grav) not longer has a strong reference to grav, and willMove(anim:) can finish and memory is released from the heap. The result will look like this:
At this point, once willMove(anim:) has finished executing, the only references remaining is the unowned self referring to the instance and some reference (e.g. let behavior = MyDropBounceAndRollBehaviour()), and then once the anonymous function has finished executing, then it will only be behaviour referencing the <MyDropAndBounceBehavior>
Do I have the correct understanding?
I will try to explain the ownership cycle in other words:
self.behaviors -> grav -> action -> self
^ created by addChildBehavior(grav)
^ created by grav.action = {
^ created by capturing
self owns the gravity behavior. The gravity behavior owns the action and the action captures (owns) self.
To break the ownership cycle, you have to break one of the connections.
One solution is to break capturing by using [weak self] or [unowned self].
Your reasoning is wrong. When a function call (e.g. willMove) is finished, no heap memory is freed. Heap memory in reference-counting memory management is released only if there are no more owners of that memory. Since the ownership cycle exist, the memory cannot be released. Threads don't really have any role in this. The same situation would happen if everything was called on the same thread (which actually can happen).
I think that your main mistake is the idea that self.addChildBehavior(grav) retains grav. That's not true. It permanently adds grav to a list of behaviors held by self, which means creating a strong ownership self -> grav.
Maybe this will help:
Self owns grav (added as a child behavior). But grav has a block that owns self (action). So now you have self that owns self, and that's a retain cycle. You can use unowned self here because if self gets deallocated, grav's block will too. You typically use unowned self in cases like this when self owns the object referring to self; otherwise, use weak self.
I need some explanation about references in closures in Swift.
Here is my use case, let's imagine we have :
class A {...}
class B {
func makeAclosure() {
let instanceA = A()
instanceA.someFunctionA(completion: {(input) in
self.someAnotherFunction(input)
})
}
}
Is there a retain cycle between class A and B or not ?
In which case it can be a retain cycle in this kind of scenario ?
It is not possible to say without looking at A.someFunctionA since it's unknown if completion is #escaping (e.g. if it's retained). For the rest of the answer I will assume that it is #escaping.
Swift needs to ensure runtime safety, and will keep any objects it might need in the future alive, in this case by making a strong reference to self (since self is the only variable used inside the closure).
In this scenario there is no reference cycle. This is because instanceA is not retained, so A => B, but B !=> A.
However, if instanceA was retained by B (let's say you create an instanceA: A property and set it) then you will have a retain cycle.
To get around this you can make variables within the closure either weak or unowned. They both do the same thing, but provide you with slightly different types. They both hold a weak reference, meaning that instanceA will not be increase the reference count of your B instance; if B is deallocated and there are no other reference, instanceA is also deallocated.
When using [weak self] self is optional, e.g. self: B?. However, [unowned self] is explicitly unwrapped, e.g. self: B!. This means that if the closure is called and self is nil your program will crash. This is why it's important to only use unowned when you know for certain that deallocating B will also deallocate A. There are a few scenarios where unowned is safe, e.g. the case when creating a closure and storing it on the same object that created it, but there are more nuances to this.
If unsure, use weak!
If your self object will potentially be deallocated before your closure is called, you should specify [weak self], so that you can avoid bad access exceptions.
If you know that it will definitely not be deallocated, then you can use [unowned self] to create a reference that will behave like an implicitly unwrapped optional.
In your example, the instance of B owns the reference to instanceA (within the context of your makeAClosure() function), so you will not end up with a retain cycle.
You should consider the implementation of someFunctionA(completion:), to determine if you need an unowned or a weak reference to self in that closure.
(A small aside: if you're using [weak self], then to avoid having optionals such as self? throughout your code, you can use guard let `self` = self else { ... } to continue using self in the closure code.
I have a function with this prototype:
func myFunction(completionHandler:((response:[NSString:AnyObject])->Void)?))
The completionHandler prototype can be passed as closure or as a function... passing it as closure I know how to define a capture list with this syntax [weak self], but how can I define a capture list if instead of defining the closure directly in the function argument I want to pass a function name?
myFunction(anotherFunction) // how to set capture list from here?
VS
myFunction{
[weak self] (response) in
}
```
EDIT-----
A possible solution is to wrap the function code into a block, set the capture list and execute the block... but it sounds so strange :/
myFunction(anotherFunction) // how to set capture list from here?
.
.
.
func anotherFunction(response:[NSString:AnyObject]) {
let safeBlock = {
[weak self] in {
self?.callSomethingSafely()
}
}
safeBlock()
}
EDIT (based on correction from Hamish below):
I'm not aware of a way to force a referenced method to internally use a weak version of a captured variable. As you have in your example, it's up to to the actual method implementation to do that or not.
However, it's worth noting that unless you are going to be storing a reference to that completion handler indefinitely, you don't need to worry about weak self.
I assume that completion handler will be called as soon as some asynchronous task that myFunction kicks off is completed. In that case, any references captured by the completion handler will only be held until the completion handler runs. Then those references will be released and there won't be any retain cycles. Weak self in closures in only important if "self" retains the closure and the closure captures "self", setting up a circular reference / retain cycle.
#MatterGoal your solution will still produce a reference cycle.
I am assuming you are aware of the situations where we should use a capture list. For a scenario like myFunction(anotherFunction), we cannot define a capture list for a method (func) named anotherFunction itself. At least for now, lets hope in future we can.
We can only define a capture for a closure. A method can act as a closure with same signature but it (method) does not support capture list for itself.
Solutions:
Make a lazy var anotherFunction = { } in which we can define capture list.
Make your function return a closure:
func anotherFunction() -> (() -> Void) {
return { [weak self] in
// do anything you want with self? properties or methods.
// this won't create a strong reference cycle
}
}
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.
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