native
native copied to clipboard
Provide guidance to avoid retain cycles with Obj-C
Weak references are an extremely common pattern in Objective-C for avoiding retain cycles or global retention, and it's not at all clear to me how to avoid leaks in the corresponding Dart code.
For instance, if I want to register an observer using addObserverForName:object:queue:usingBlock: the common pattern—indeed, Apple's docs recommend this—is to have self be a weak reference in the block. Then dealloc can make the required call to removeObserver:, and there's no risk of leaking an object. ~There's no way that I'm aware of to make a weak reference in Dart, which means I need to instead find some explicit point to remove that observer, and if I don't, or if I mess up and there are cases where it's not called, then I leak the object forever, because there's a retain that Dart doesn't know about or control.~
~If we don't have some way of replicating the weak reference pattern in Dart, then Dart-Obj-C-FFI code is going to be more error prone than the corresponding Obj-C code, which is very problematic since we don't want an ecosystem of plugins that are much more likely to have leaks than we would without ffigen. Perhaps objective_c should provide a little native weak-wrapper class that on the native side is nothing but a weak id property, and on the Dart side is a templated class that down-casts the access to the template type?~
Since I'm probably in the majority in not being familiar with WeakReference, we should prominently document how to replicate this pattern in Dart.
(This is essentially the Obj-C version of #575)
There's no way that I'm aware of to make a weak reference in Dart,
https://api.flutter.dev/flutter/dart-core/WeakReference-class.html
Edit: Although I'm not sure if this works out of the box with the obj-c object type.
Ah, right 🤦🏻 I have actually encountered that once (in the wrapper generator code), but forgot it existed.
Updated to make this a docs request rather than a functionality request.
Edit: Although I'm not sure if this works out of the box with the obj-c object type.
I don't know that it really has to. The usual pattern is a weak reference to self, and in the context of Dart FFI code, self (i.e., this) is going to be a regular Dart object.
@stuartmorgan If you try out WeakReference, let me know if solves this case. My hunch is that it won't actually work, and we're going to need something specific in package:objective_c.
WeakReference does solve my use case.
In retrospect, the now-crossed-out suggestion in my initial post wouldn't have worked, because the use case I have isn't wiring up a weak reference to a native object, it's needing a weak reference to a Dart object in a block that's ultimately owned by native code. The Dart->Native weak reference case could exist, so maybe we'll still need that, but the common case that I was thinking of is solved by WeakReference.