Is it possible to get the retain count of a Closure in Swift? - swift

In Swift, Closures are reference types. Which means (I think, please correct me if I'm wrong) that they have a lifetime managed by a retain count. I can get the retain count of an object using CFGetRetainCount, but this doesn't work for Closures because they can't conform to AnyObject (or any protocol for that matter).
Before anyone jumps in and tells me I'm doing the wrong thing by trying to get the retain count of anything manually, I know. It's purely for experimentation to prove to myself that this is how Closure lifetime is managed by the runtime.

You can use CFGetRetainCount if you declare the closure as #convention(block), as this will instruct the compiler to generate an Objective-C block, which is for all intended purposes an object:
let closure: #convention(block) () -> Void = {
print("test")
}
print(CFGetRetainCount(unsafeBitCast(closure, to: CFTypeRef.self)))

Related

How to get UnsafeRawPointer on the swift object?

My app uses the native C++ lib, there is a method that takes as an argument void*
void foo(void * obj) { ... }
in swift I can call this method like this
func boo(obj: MyCustomObj) {
foo(&obj)
}
and looks like really I get a void pointer on the object, but if I try to get an UnsafeRawPointer on the object like this
func boo(obj: MyCustomObj) {
var pointer = &obj <---- Use of extraneous '&'
foo(pointer)
}
I got an error
Use of extraneous '&'
What is the problem here?
EDIT
I understood that using withUnsafe*** I can get the pointer to the data, but what to do if my method has 2 params, would it looks like this
withUnsafePointer(to: myObjFirst) {
pFirst in
withUnsafePointer(to: myObjSecond) {
pSecond in
foo(pFirst, pSecond)
}
}
The & syntax does not mean "the address of" or "pointer to" like in C. In Swift, it is an in-out expression.
These can be used to create implicit pointer conversions as a convenience, and that can seem like C's "pointer to" meaning, but it has very different rules and behaviors. For example, there is no promise that obj even has an address. It may be a tagged pointer. Passing it via an in-out expression may allocate memory and copy the value to make the call possible. Similarly, when passing a "pointer to an array," Swift will actually pass a pointer to a contiguous block of values (which may have been copied to make them contiguous) which is not the same as the actual Array struct.
It is not meaningful to say var pointer = &obj. There is no in-out reference there.
There is no general way to take long-lived pointers to objects in Swift without allocating your own memory (and this is rare). The memory model doesn't promise the kinds of lifetimes you'd need to make that sensible. If your code did compile the way you expect it to, the call to foo(pointer) would still be invalid because there's no promise that obj exists at that point and the pointer could be dangling. (There are no references to obj after the first line, so Swift can and often will destroy it, even though it's still "in scope.")
The foo(&obj) syntax is basically a shorthand for:
withUnsafePointer(to: obj) { foo($0) }
It exists to make it easier to call C functions, but it doesn't mean that Swift pointers are anything like C pointers.
For much more on Swift pointers, see Safely manage pointers in Swift from WWDC 2020.

Closures and static funcs

I have a ViewModel class with a method like this:
func getUserSettings() {
UserSettingsManager.getInfo { (result, error) in
if error == nil {
self.userData = result
}
}
}
This class viewModel is instantiated and then viewModel.getUserSettings() is called. Such method is calling a static method UserSettings.getInfo which is passed an #escaping closure to be called as completion. That closure is capturing viewModel (it's using self within it's body).
What consequences does calling a static method have in terms of memory? How would that UserSettings class that is not instantiated be "deallocated"?
Could a strong reference cycle happen in this particular scenario? If so, how should self be captured: weak or strong?
What consequences does calling a static method have in terms of
memory? How would that UserSettings class that is not instantiated be
"deallocated"?
In the context of your question, the fact that the function is static doesn't have any special memory implications. Static methods have just as much potential to create reference cycles as non-static ones.
As you said, if there is no instance of UserSettingsManager, no instance will be deallocated. This fact alone does not eliminate the potential for reference cycles.
Could a strong reference cycle happen in this particular scenario? If so, how should self be captured: weak or strong?
Depending on what happens within getInfo, this could create a reference cycle. While, it seems unlikely, it's impossible to say for sure with the snippet you've posted.
For clarification, I should mention that you're currently capturing self strongly, which is default. This means the closure increments the strong reference count of the instance of self so that it can successfully interact with that instance when the closure is eventually invoked. To override this behavior and avoid a reference cycle, you'd use [weak self].
Finally, to visualize your current approach, you could think of it in the following manner:
UserSettingsManager → closure → self
That's a nice clean chain! A reference cycle would only occur if one of those links gained a reference back to another.

Swift - Capture List self clarification

After reading some articles and developer guide of apple, i'm still confused about Capture List in closure.
What does it mean "capture", how does it work behind the scene in terms of unowned self and weak self? how the closure use self without owning the object?
I thought it like making a copy of that object so when it get finished it's passed from the stack like value type, but i guess that i'm wrong.
I'm hoping that someone here can make it more easier and clear for understanding, or linked me to a good article that answering this specific question.
Thanks for advance
My understanding, and it might be a bit simplified, is that it is about ownership and holding on to an object, meaning that as long as we claim ownership of an object it can not be freed from memory even another part of the code sets it to nil or similar.
With weakwe say that it is okay to destroy the object and that we will only use it if it is still around.
So when declaring self as weak in a closure we say that if self is still around when it's time to execute the closure we do so normally otherwise the closure will silently be ignored without generating an error.
It's mainly to do with reference counting. Any instance that is used inside a closure (but was declared outside) is strongly referenced (i.e. its reference count is incremented). This can lead to retain cycles, e.g.
class MyClass {
var myClosure: (() -> Void)!
init() {
myClosure = {
self.foo()
}
}
func foo() {
}
}
In the above example the instance of MyClass retains a reference to myClosure and vice versa, meaning that the MyClass instance will stay in memory forever.
You can also have more complex/harder-to-spot retain cycles, so you need to really pay attention and if you ever have any doubts add some print calls to your class' deinit methods just to make sure (or use Instruments).
In order to avoid these issues you can mark objects being captured in closures as unowned or weak. This means that their reference count won't be increased and you can avoid these retain cycles. The above example could have either been done this way:
myClosure = { [weak self] in
self?.foo()
}
or, better yet for this example, this way:
myClosure = { [unowned self] in
self.foo()
}
While the first way is always safe and what you will more likely do, the unowned version is easy to reason in this example because you know that myClosure won't outlive self. However, if you're not 100% sure that self will always outlive the closure use weak.
Also note that you can mark how to capture multiple objects used inside the closure, just separate it by commas, e.g.
myClosure = { [weak self, unowned bar] in
self?.foo(bar)
}
If we keep in mind that captured values are strong references in closures by default, we can assume that this can create retain cycles (bad stuff).
A capture list is an array of variables you can pass into a closure. The purpose of capture lists is to change the strenght of the variables that are passed in. This is used to break retain cycles.
For instance:
// strong reference
[label = self.myLabel!] in
// weak reference
[weak label = self.myLabel!] in
// unowned reference
[unowned self] in

Swift - Avoiding strong reference cycles in closure-based configuration

Please note: I have read many of the (very many) answers and articles on the subject of avoiding strong reference cycles. However, I'm looking for guidance on how to handle a specific by-product of avoiding these cycles.
In the following example, the class Foo is designed to be configured using a closure. A reference to the closure is cached for later use.
The closure will be called whenever the Model data is needed. In order for Foo to work properly, the data must exist.
class Foo
{
typealias ModelGetter = (() -> Model)
fileprivate var _modelGetter: ModelGetter!
...
func configure(with modelGetter: #escaping ModalGetter)
{
_modelGetter = modelGetter
}
func printLastestModel()
{
// Get the latest model, do something with it.
precondition(_modelGetter != nil)
let model = _modelGetter()
print(model)
}
}
In the above code, _modelGetter is implicitly unwrapped. Although I could define it as an Optional, and unwrap it as needed, Foo always needs the closure to be set in order to work properly, hence the implicit unwrapping.
Making an instance of Foo, and configuring it:
let foo = Foo()
foo.configure(with: { self.makeModel() })
foo.printLatestModel()
But, this creates a retain cycle.
So, [weak self] is used, and we check for self's optionality:
foo.configure(with: { [weak self] in
guard let strongSelf = self else { return **WHAT** }
return strongSelf.makeModel()
})
Problem
This requires that even though self may be nil, the closure still needs to return a Model (i.e. WHAT?) to the caller of the closure (the Foo instance.) But, since self is nil, I don't have a Model to hand over.
Question
Can someone recommend a pattern to use in this situation? Preferably, I don't want Foo to be checking if the modelGetter is valid or not, or left wondering if the Model is valid. For Foo's purposes, if Foo exists, then it must always be able to get the Model it needs.
Or, should I just redesign Foo's needs, to take in to account the possibility of not being able to procure a Model? Thankyou for any help.
If Class is the owner of Foo, it's recommended to set [unowned self] instead of [weak self]. It will solve the problem. If one class is the owner of another it will never appear as a problem, but if the logic is wrong it will appear a crash. This is not bad because it signals to you that you broke something in the project.
But, this creates a retain cycle.
No it doesn't. foo owns a reference to the closure and the closure owns a reference to self (which is clearly not foo). You will only get a retain cycle, if you have a strong property of type Foo in self and you set it to foo.
On the assumption that you are going to do that, I would use one of two patterns:
I make the assumption as a programmer that self will always be there for the lifetime of foo. In that case, I would use [unowned self] instead of [weak self]. If my assumption proves to be wrong, the program will abort and I'll be able to fix the bug based on the stack trace. Obviously, you'll want a fairly extensive test suite to validate the assumption as far as possible.
I decide that it is valid for self to disappear in which case you have three choices about how to handle the disappearance:
Make the return type of the closure optional i.e. () -> Model? and make Foo capable of handling a nil model
Have a default Model that you return if self is nil.
Make the closure declare that it throws and throw an error if self is nil.
I think I'd probably go with [unowned self] and make sure I explicitly kept a strong reference to it somewhere.

How do I manually retain in Swift with ARC?

I'm using Swift 3 with ARC in an iOS app, and I want to manually retain an object.
I tried object.retain() but Xcode says that it's unavailable in ARC mode. Is there an alternative way to do this, to tell Xcode I know what I'm doing?
Long Version:
I have a LocationTracker class that registers itself as the delegate of a CLLocationManager. When the user's location changes, it updates a static variable named location. Other parts of my code that need the location access this static variable, without having or needing a reference to the LocationTracker instance.
The problem with this design is that delegates aren't retained, so the LocationTracker is deallocated by the time the CLLocationManager sends a message to it, causing a crash.
I would like to manually increment the refcount of the LocationTracker before setting it as a delegate. The object will never be deallocated anyway, since the location should be monitored as long as the app is running.
I found a workaround, which is to have a static variable 'instance' that keeps a reference to the LocationTracker. I consider this design inelegant, since I'm never going to use the 'instance' variable. Can I get rid of it and explicitly increment the refcount?
This question is not a duplicate, as was claimed, since the other question is about Objective-C, while this one is about Swift.
The solution turned out to be to re-enable retain() and release():
extension NSObjectProtocol {
/// Same as retain(), which the compiler no longer lets us call:
#discardableResult
func retainMe() -> Self {
_ = Unmanaged.passRetained(self)
return self
}
/// Same as autorelease(), which the compiler no longer lets us call.
///
/// This function does an autorelease() rather than release() to give you more flexibility.
#discardableResult
func releaseMe() -> Self {
_ = Unmanaged.passUnretained(self).autorelease()
return self
}
}
This is easily done with withExtendedLifetime(_:_:) function. From the documentation:
Evaluates a closure while ensuring that the given instance is not destroyed before the closure returns.
Cheers!