Archimedes for Mac uses (WebKit 1) WebViews to render live previews of documents. While working on improved cache management for the next release of Archimedes, I noticed WebView
allocations were not going down as documents were being closed. What’s more, the PreviewViewController
s that own the WebView
s were also not being deallocated.
I had a hunch retain cycles were to blame, so I launched Instruments and ran the Allocations instrument with the Record reference counts option turned on. Immediately, it became clear what was happening. PreviewViewController
, which maintains a strong reference to the WebView
, was being exported to JavaScriptCore
as a JSExport
as such:
Here, JavaScriptCore
was creating a strong reference back to the PreviewViewController
, thus creating a strong reference cycle.
I tried unloading the page right before the document closes hoping the WebView
would relinquish control of the PreviewViewController
, but it did not work as I expected.
Next, instead of passing the entire view controller to JavaScriptCore
, I decided to create a new class whose sole purpose is to relay messages to a weakly-referenced delegate object:
And the JavaScriptContext
was now set up as follows:
Now, while JavaScriptCore
still retains the proxy object, it no longer retains our PreviewViewController
since it is weakly-referenced. This allows the WebView
to get destroyed when the document is closed, and a moment later the PreviewViewMessenger
disappears along with it. As the saying by David Wheeler goes, maybe all problems in computer science really can be solved by adding a level of indirection. 😊