ylliX - Online Advertising Network
Vertex AI - Antrophic and Mistral models: Why does it require Imegen access?

Am i doing something wrong with implementation of UITabBarController or there is some bug with it? UITabBarItem memory leak


I’m quite new with iOS development and while testing for leaks found out that UITabBaritem isn’t deallocating and have 1:1 reference with UITabBarItemBridgedElement

I’m using Xcode 16 with support from iOS 15.

ref image
enter image description here
enter image description here

so i was wondering if this is because of my implementation or there is some Apple bug with it?

MVP

class MainViewController: UIViewController {
    
    var button: UIButton = {
        var config = UIButton.Configuration.filled()
        config.cornerStyle = .capsule
        config.title = "Tap me"
        config.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 20, bottom: 5, trailing: 20)
        config.baseBackgroundColor = .tintColor
        
        let button = UIButton(configuration: config)
        
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        title = "Main View Controller"
        
        view.backgroundColor = .white
        
        button.translatesAutoresizingMaskIntoConstraints = false
        button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
        view.addSubview(button)
        NSLayoutConstraint.activate([
            button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)
        ])
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        print("MAIN WILL APPEAR")
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        
        print("VC \(self)\(title) recieved mem warning")
    }
    
    override func willMove(toParent parent: UIViewController?) {
        super.willMove(toParent: parent)
        
        print("VC \(self)\(title) will move to parent")
    }
    
    @objc
    func buttonAction() {
        let redVC: UINavigationController = createRedNVC()
        let greenVC: UINavigationController = createGreenNVC()
        let blueVC: UINavigationController = createBlueNVC()
        
        let tabBarVC = TabBarController()

        tabBarVC.setViewControllers([redVC, greenVC, blueVC], animated: false)
        
        navigationController?.pushViewController(tabBarVC, animated: true)
    }
    
    private func createRedNVC() -> UINavigationController {
        let root = ViewControllerRed()
        let nav = UINavigationController(rootViewController: root)
        
        nav.tabBarItem = UITabBarItem(title: "Red", image: nil, tag: 0)
        
        return nav
    }
    
    private func createGreenNVC() -> UINavigationController {
        let root = ViewControllerGreen()
        let nav = UINavigationController(rootViewController: root)
        
        nav.tabBarItem = UITabBarItem(title: "Green", image: nil, tag: 0)
        
        return nav
    }
    
    private func createBlueNVC() -> UINavigationController {
        let root = ViewControllerBlue()
        let nav = UINavigationController(rootViewController: root)
        
        nav.tabBarItem = UITabBarItem(title: "Blue", image: nil, tag: 0)
        
        return nav
    }
}

class ViewControllerBlue: UIViewController {
    
    deinit {
        print("OS reclaiming memory for ViewControllerBlue")
//        tabBarItem = nil
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .blue
        title = "Blue"
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        
        print("VC \(self) recieved mem warning")
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        print("VC \(self) will disappear")
    }
    
    override func willMove(toParent parent: UIViewController?) {
        super.willMove(toParent: parent)
        
        print("VC \(self) will move to parent:\(parent)")
    }
}

class ViewControllerRed: UIViewController {
    
    deinit {
        print("OS reclaiming memory for ViewControllerRed")
//        tabBarItem = nil
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .red
        title = "Red"
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        
        print("VC \(self)\(title) recieved mem warning")
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        print("VC \(self)\(title) will disappear")
    }
    
    override func willMove(toParent parent: UIViewController?) {
        super.willMove(toParent: parent)
        
        print("VC \(self)\(title) will move to parent:\(parent)")
    }
}

class ViewControllerGreen: UIViewController {
    
    deinit {
        print("OS reclaiming memory for ViewControllerGreen")
//        tabBarItem = nil
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
       
        view.backgroundColor = .green
        title = "Green"
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        
        print("VC \(self)\(title) recieved mem warning")
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        print("VC \(self)\(title) will disappear")
    }
    
    override func willMove(toParent parent: UIViewController?) {
        super.willMove(toParent: parent)
        
        print("VC \(self)\(title) will move to parent:\(parent)")
    }
}

class TabBarController: UITabBarController {
    
    deinit {
        print("OS reclaiming memory for TabBarController")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.delegate = self
        
        self.tabBar.backgroundColor = .systemGray
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        guard let navigationController else { return }
        print("TabBarController will disappear, navController: \(navigationController)")
    }
    
    override func willMove(toParent parent: UIViewController?) {
        super.willMove(toParent: parent)
        
        print("TabBarController will move to parrent: \(parent) \(self.viewControllers)")
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        
        print("TabBarController recieved mem warning")
    }
}

extension TabBarController: UITabBarControllerDelegate {
    func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
        print("Selected: \(viewController)")
    }
}

And from Instruments>Leaks i get this
enter image description here
enter image description here

Only thing that seems to work is to set tabBarItem = nil in deinit in every VC.

I’ve tried every solution that i could find here, without success

If someone have experience with this would be much appreciated, pulling my hair for few days now about this problem



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *