Could someone help me understand what's going on here?

Please watch this video of my app, basically when I login as a user, my profile tab works perfectly, but as soon as I click the search button and create a new instance of my profile controller, the profile tab, does not work. It feels like the memory is being overwritten.

Code Block
https://streamable.com/4yhxgd


Could you please post code, that will be needed to provide any help.

May be you are creating a new instance of some object, hence you don't access the one you need to access later.

But please show code.
Hi, this is my tab view controller which initialises ProfileController(...)

Code Block //
//  MainTabBarController.swift
//  AWSFullStackSocial
//
//  Created by Develoment on 20/07/2020.
//  Copyright © 2020 Develoment. All rights reserved.
//
import UIKit
class MainTabBarController: UITabBarController, UITabBarControllerDelegate, UINavigationControllerDelegate {
    
    let viewModel: ViewModel
    
    //lazy load so we can inject our viewModel
    private lazy var homeController = HomeController(viewModel: self.viewModel)
    private let imagePickerController = UIViewController()
    lazy var profileController = ProfileController(viewModel: self.viewModel, user: self.viewModel.currentUser.value)
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
        setupComponents()
    }
    fileprivate func setupComponents() {
        
        let homeTabBarController = UINavigationController(rootViewController: self.homeController)
        homeTabBarController.tabBarItem.image =  imageLiteral(resourceName: "home")
        
        let imagePickerTabBarController = UINavigationController(rootViewController: self.imagePickerController)
        imagePickerTabBarController.tabBarItem.image =  imageLiteral(resourceName: "plus")
        
        let profileTabBarController = UINavigationController(rootViewController: self.profileController)
        profileTabBarController.tabBarItem.image =  imageLiteral(resourceName: "home")
        
        self.viewControllers = [homeTabBarController, imagePickerTabBarController, profileTabBarController]
    }
    
    
    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
        if self.viewControllers?.firstIndex(of: viewController) == 1 {
            let imagePicker = UIImagePickerController()
            imagePicker.delegate = self
            self.present(imagePicker, animated: true)
            return false
        }
        
//        if self.viewControllers?.firstIndex(of: viewController) == 2 {
//            if let user = self.viewModel.currentUser.value {
//                self.profileController.user = user
//            }
//        }
        
        return true
    }
    
    init(viewModel: ViewModel) {
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
    }
    
    func refreshPosts() {
        self.homeController.refreshPosts()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}


Here is my search view controller which initialises a new ProfileController(...)

Code Block
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let user = self.users[indexPath.row]
        let controller = ProfileController(viewModel: self.viewModel, user: user, isEditable: false)
        self.navigationController?.pushViewController(controller, animated: true)
    }


in full
Code Block import UIKit
import JGProgressHUD
import PromiseKit
class SearchUserController: UIViewController, FollowUnfollowUserDelegate, UICollectionViewDelegate {
    
    fileprivate let viewModel: ViewModel
    
    fileprivate var users = [User]() {
        didSet {
            print("Users set: \(users)")
            self.updateDataSourceWith(users: users)
        }
    }
    
    var delegate: RefreshPostsDelegate?
    
    enum Section: CaseIterable {
        case main
    }
    
    fileprivate var collectionView: UICollectionView! = nil
    fileprivate var datasource: UICollectionViewDiffableDataSource<Section, User>! = nil
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupComponents()
        configureDataSource()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        let hud = JGProgressHUD(style: .dark)
        hud.textLabel.text = "Loading..."
        hud.show(in: self.view)
        self.viewModel.searchForUsers { result in
            switch result {
            case .success(let users):
                self.users = users
            case .failure(let error):
                print("Error retrieving users: \(error)")
            }
            hud.dismiss(animated: true)
            
            self.viewModel.getFollowingPosts { (result) in
                switch result {
                case .success(let post):
                    print(post)
                case .failure(let error):
                    print("Failed to retrieve following: \(error)")
                }
            }
        }
    }
    
    init(viewModel: ViewModel) {
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
    }
    
    
    private func createLayout() -> UICollectionViewLayout {
        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0))
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        
        let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(50))
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
        
        let section = NSCollectionLayoutSection(group: group)
        
        let layout = UICollectionViewCompositionalLayout(section: section)
        
        return layout
    }
    
    fileprivate func setupComponents() {
        self.navigationItem.title = "Search"
        self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
        
        self.collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: self.createLayout())
        self.collectionView.backgroundColor = .systemBackground
        self.collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        self.collectionView.alwaysBounceVertical = true
        self.collectionView.isScrollEnabled = true
        self.collectionView.register(SearchUserCell.self, forCellWithReuseIdentifier: SearchUserCell.reuseIdentifier)
        
        self.collectionView.delegate = self
        self.view.addSubview(collectionView)
    }
    
    fileprivate func configureDataSource() {
        self.datasource = UICollectionViewDiffableDataSource<Section, User>(collectionView: self.collectionView) {
            (collectionView: UICollectionView, indexPath: IndexPath, user: User) -> UICollectionViewCell? in
            
            guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SearchUserCell.reuseIdentifier, for: indexPath) as? SearchUserCell else { fatalError("Cannot create cell")}
            
            cell.nameLabel.text = self.users[indexPath.row].fullName
            cell.item = user
            cell.delegate = self
            return cell
        }
    }
    fileprivate func updateDataSourceWith(users: [User]) {
        var snapshot = NSDiffableDataSourceSnapshot<Section, User>()
        snapshot.appendSections([.main])
        snapshot.appendItems(users)
        self.datasource.apply(snapshot, animatingDifferences: true)
    }
    
    func handleFollow(cell: UICollectionViewCell) {
        let hud = JGProgressHUD(style: .dark)
        hud.textLabel.text = "Following..."
        hud.show(in: self.view)
        print("Handle Follow")
        
        guard let indexPath = self.collectionView.indexPath(for: cell) else { return }
        
        let user = self.users[indexPath.row]
        self.viewModel.followUnfollow(user: user) { (result) in
            switch result {
            case .success(let user):
                self.users[indexPath.row].isFollowing = user.isFollowing
                self.delegate?.refreshPosts()
                hud.dismiss()
                self.dismiss(animated: true)
            case .failure(let error):
                print("Failed to follow / unfollow user: \(error)")
            }
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let user = self.users[indexPath.row]
        let controller = ProfileController(viewModel: self.viewModel, user: user, isEditable: false)
        self.navigationController?.pushViewController(controller, animated: true)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}



You are right, I am creating a new instance of the object, ProfileController, but I thought that it would be a self contained instance, and the existing would not be touched by the new one?
You create a newController, and then push it on the navigation stack with
Code Block
let controller = ProfileController(viewModel: self.viewModel, user: user, isEditable: false)       
self.navigationController?.pushViewController(controller, animated: true)

So you end up with several controllers stacked over each time you select an item.

Where and how is ProfileController defined ? Have you a viewController associated with it ?
If so, why do you push a new one each time you select an item ?
You could have a Show (push) segue from the first VC to ProfileController VC and fire the segue when you select.

Note: when you paste code, use the Paste and Match Style, to avoid the stupid behaviour of this forum that adds extra lines.

One more thing.

If I understand your code well enough, if you want to push, why don''t you push the profileController that exists, after setting its properties to the relevant values ?
Could someone help me understand what's going on here?
 
 
Q