Design patterns for avoiding memory cycles

Say I have a view controller that has a helper object that keeps a reference to the controller. I have a cycle, so the helper’s reference should be a weak var. Now all the methods in the helper that use the controller need a guard to deal with the unlikely case that it’s been deallocated. Another design would be to have all the helper methods take the controller as a extra parameter.

How are people handling these situations? I’m wondering if there are some Swift design patterns here that I don’t know about.

You can declare your property as unowned. That makes it non-optional and yet avoids retain cycles. However, you’ll lose any help from the compiler in keeping your code safe. It’s up to you to review your code for any possibile access-after-free.

If it is logically permissible to be nil and you simply want to ignore it in that case (similar to ObjC nil messaging) then simply use optional chaining:

controller?.doSomething()

doSomething() will only be called if controller is not nil.

Just to clarify slightly, your code is still memory-safe, meaning there won't be memory corruption or segfaults, as access-after-free is still detected at run-time and converted into a reliable abort (which isn't good, but usually better than memory unsafety).

1 Like

First of all: Why do methods in the helper object need the controller?

If they are coupled tightly, just move those methods into an extension of the controller. Moving methods to a helper type just for the sake of it, without thinking about the coupling and architecture, isn't really worth it imo.

If the helper object just needs the controller to customize behavior or provide info about completion/events that occured/..., delegation would be the classic design pattern, but doesn't really help you with checking whether the delegate is nil, and to me feels a bit outdated for Swift (although it still does it's job just fine).

For customization of behavior where something like having no delegate would not make sense, I've had some success with passing closures (or a struct of many closures, for better structure :roll_eyes:) into the initializer of your helper. The closures might still be mutable members so you can change the behavior, but can never be nil. But be aware that this only shifts the burden of deciding about memory management to the user, who will have to use weak refs or similar in the closure itself, to prevent a retain cycle.

For the special case of notifying a consumer of an api that something finished, I've found promises to be a great tool. They also use closures, but most implementations will deallocate those as soon as they are run, which makes potential cycles only live as long as the event, which is often precisely what you want.

Yes, I was thinking of that. My helper needs some instance variables, so if it were an extension, it would need variables in the main class definition. The classes are a DocumentViewController, which is the largest class in my app, and the helper that handles undo/redo functionality. Maybe the undo thing can work with a reference to the model instead. I start wanting separate classes just because the controller file is getting big and hard to scroll around... not a great reason for a design decision...

I have found the coordinator pattern very good in breaking down giant view controllers:

http://khanlou.com/2015/10/coordinators-redux/

I’m not sure if it helps in your case, though. It sounds like undo/redo should be a part of the model.