UIViewControllerRepresentable memory leak with SwiftUI

I have created a very simple example of how a UIViewController represented by UIViewControllerRepresentable is never deallocated.


struct ContentView : View {
    @State private var showRepView = true
    
    var body: some View {
        VStack {
            Text("Square").font(.largeTitle).tapAction {
                self.showRepView.toggle()
            }
            
            if showRepView {
                SomeRepView().frame(width: 100, height: 200)
            }
        }

    }
}


The representation implementation follows:


struct SomeRepView: View {
    var body: some View {
        RepViewController()
    }
}

struct RepViewController: UIViewControllerRepresentable
{
    func makeUIViewController(context: Context) -> SomeCustomeUIViewController {
        let vc =  SomeCustomeUIViewController()
        print("INIT \(vc)")
        return vc
    }
    
    func updateUIViewController(_ uiViewController: SomeCustomeUIViewController, context: Context) {
    }
    
    static func dismantleUIViewController(_ uiViewController: SomeCustomeUIViewController, coordinator: Self.Coordinator) {
        print("DISMANTLE")
    }
    
}

class SomeCustomeUIViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.green
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        print("viewWillDissapear \(self)")
    }
    
    deinit {
        print("DEINIT \(self)")
    }
    
}

By tapping on the "Square" button,

SomeRepView
is added and removed alternatively. However, the related UIViewController is never released.


That can be seen by the logged messages and I also confirmed with Instruments.


Note that SomeRepView is released properly. It is only the corresponding view controller what remains allocated.


Also note that the

UIViewController.viewWillDissappear
is called and also the
UIViewControllerRepresentable.dismantleUIViewController


This is a typical output when pressing the Square button repeatedly.


INIT <SomeCustomeUIViewController: 0x100b1af70>
DISMANTLE
viewWillDissapear <SomeCustomeUIViewController: 0x100b1af70>
INIT <SomeCustomeUIViewController: 0x100a0a8c0>
DISMANTLE
viewWillDissapear <SomeCustomeUIViewController: 0x100a0a8c0>
INIT <SomeCustomeUIViewController: 0x100b23690>
DISMANTLE
viewWillDissapear <SomeCustomeUIViewController: 0x100b23690>


As shown,

DEINIT
is never printed.


Running with iOS13, beta 2, iPad 6th Gen and on the simulator. I also tried triggered a Simulate Memory Warning. But no effect. The controllers persist in memory.


My question is... is it a bug? Or am I doing something wrong?

Post not yet marked as solved Up vote post of kontiki Down vote post of kontiki
3.3k views

Replies

Problem still present with Xcode 11 beta 4.

I have the same issue, did you find a solution ?

Seeing this in Xcode 13.4.1. Any updates?