Weak property deallocation confusion
Weak property deallocation confusion
I'm using a third party library and it required setting a delegate. In this scenario I want to set the delegate to be another class so I go to write
ThirdPartyLibrary.delegate = MyDelegateHandlerClass()
But Xcode (Xcode 10 beta) gives me a warning saying:
Instance will be immediately deallocated because property ‘delegate’
is ‘weak’
Clicking into the delegate
of the third party library I see that it is indeed defined as weak
as follows:
delegate
weak
@property (weak, nonatomic) id<ThirdPartyLibraryDelegate> delegate;
However, if I change my initial setting of the delegate to:
let someInstance = MyDelegateHandlerClass()
ThirdPartyLibrary.delegate = someInstance
Then I get no warning? How are these two not the same thing? Just looking for advice and an explanation really. Thanks!
2 Answers
2
They are, in effect, the same thing. Once someInstance
goes out of scope the delegate handler will be released and the delegate property of the library will become nil
.
someInstance
nil
In the first case the compiler can see that the result of an allocation is being assigned to a weak
property and warn you that it will be immediately released, which is probably not what you want.
weak
In the second case it sees the assignment to a local variable and so the object will remain in memory for some time. The compiler cannot determine that you didn't want the object to be released at the end of the function, which means that it doesn't warn you.
You will need to store a strong reference to the delegate handler in a property
Ah makes sense! Now let's say all of this is going on in a struct, at the top of the struct I could just declare
private static let someInstance = MyDelegateHandlerClass()
and then assign that to the delegate
and that would be ok?– Mr.P
Jun 29 at 10:50
private static let someInstance = MyDelegateHandlerClass()
delegate
Yes, that would work.
– Paulw11
Jun 29 at 10:51
You get no warning in second case, but it will get deallocated as well, because someInstance
is a local variable - will be deallocated when you leave the scope where it was declared.
someInstance
What you need to do is store your MyDelegateHandlerClass
instance somewhere. If you are certain that you will use only one instance of MyDelegateHandlerClass
, you can use a Singleton pattern:
MyDelegateHandlerClass
MyDelegateHandlerClass
class MyDelegateHandlerClass : ThirdPartyLibraryDelegate
{
static let sharedInstance = MyDelegateHandlerClass()
// class implementation
}
(...)
ThirdPartyLibrary.delegate = MyDelegateHandlerClass.sharedInstance
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
For anyone interested, this warning was recently implemented in github.com/apple/swift/pull/14875 :)
– Hamish
Jun 29 at 12:18