Can't push to another view controller

Hi guys, I have a view controller. Within this view controller, I have a subview named SearchUserSubView containing a table view.

Since I am not able to push to another view controller within this view, I tried to do following thing:

class SearchUserSubView:UIView {
...
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        let userCell = tableView.cellForRow(at: indexPath) as! SearchUserTableViewCell
        let userObject = userResultArray[indexPath.row]
        
        // if the profile image is not loaded, don't allow clicking on the cell
        if(userCell.profileImageView.image == nil) {
            return
        }
        
        let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
        let searchContentController = storyBoard.instantiateViewController(withIdentifier: "searchContent") as! SearchContentViewController
        searchContentController.showProfileViewController(userObject: userObject, userProfileImage: userCell.profileImageView.image!)
    }

I am trying to call the showProfileViewController method, defined in my view controller class. And it is actually called:

func showProfileViewController(userObject: User, userProfileImage: UIImage) {
        let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
        let selectedUserController = storyBoard.instantiateViewController(withIdentifier: "selectedUserProfile") as! SelectedUserProfileViewController
        selectedUserController.userObject = userObject
        selectedUserController.userProfileImage = userProfileImage
        let navController = storyBoard.instantiateViewController(withIdentifier: "searchContentNav") as! UINavigationController
        navController.pushViewController(selectedUserController, animated: true)
    }

Whatever I do here, nothing is pushed towards the SelectedUserProfileViewController.

Can anyone tell me, why this is the case?

Replies

Tried doing a segue instead of a push?

What do you expect to be pushed ?

I expect that I am redirected to another view controller.

another view controller

You instatiate multiple view controllers, which one do you want to show?


And I cannot find any code where the current view controller does `present` the next view controller.

let navController = storyBoard.instantiateViewController(withIdentifier: "searchContentNav") as! UINavigationController  
        navController.pushViewController(selectedUserController, animated: true) 

I want to push to selectedUserController.

Then, why don't you write a code to `present` the `selectedUserController`? Why do you need `navController`?

It's because, I want to keep the tabbar.

Do you understand that newly instantiated view contoller does nothing for you?


You instantiate a new `UINavigationController` and it is not displayed on the screen nor does not exist anywhere in the view/view controller hierarchy.

Calling `pushViewController` on such a `UINavigationController` has no effect.

  • If you'd tell him what he didn't do instead of telling him what he did do then I guess we newbies would save a lot of time, wouldn't we?

Add a Comment

But even if try to execute

self.navigationController.pushViewController(...

nothing happens. And my view controller is embedded in a navigation controller.

It depends on what is `self`. Assume `self` is your `searchContentController`, then it does nothing.


And my view controller is embedded in a navigation controller.

Then you need to access the very view contoller currently displayed. Do not instantiate a new view controller.

Indeed, 'self' is actually SearchContentViewController. But I haven't understood what you meant with accessing the very first view controller currently displayed. How can I do that? Sorry for asking.

I guess an instance of your `SearchContentViewController` is displayed in a `UINavigactionController`. You need to access the instance currently displayed. Maybe you may need a delegate pattern, to make your code work. But as you are not showing any code of `SearchContentViewController`, I cannot show you how.

Thanks for your help. Appreciate it a lot. I put you more code now 🙂
First my SearchUserSubView:

protocol SearchUserSubViewDelegate {
    func showProfileViewController(userObject:User, userProfileImage:UIImage)
}

class SearchUserSubView:UIView {
    
    // ui components
    var userTableView = UITableView()
    
    // array as datasource for the table view
    var userResultArray = [User]()
    
    // variable for interacting with the database
    let dataAccess = DataAccessService()
    
    var delegate:SearchUserSubViewDelegate?
...
}

extension SearchUserSubView:UITableViewDataSource {

 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        let userCell = tableView.cellForRow(at: indexPath) as! SearchUserTableViewCell
        let userObject = userResultArray[indexPath.row]
        
        // if the profile image is not loaded, don't allow clicking on the cell
        if(userCell.profileImageView.image == nil) {
            return
        }
        
        delegate?.showProfileViewController(userObject: userObject, userProfileImage: userCell.profileImageView.image!)
    }
}

Now my SearchContentViewController:

// view controller for providing search filters
class SearchContentViewController: UIViewController {
    
    var searchUserSubView = SearchUserSubView(frame:CGRect(x: 0, y: 0, width: 0, height: 0))
// called in viewDidLoad
func setupView() {
            
        let searchUserSubViewFrame = CGRect(x: 0, y: self.textFieldContainer.frame.maxY, width: self.view.frame.width, height: self.view.frame.height * (440/self.view.frame.height))
        self.searchUserSubView = SearchUserSubView(frame: searchUserSubViewFrame)
        self.searchUserSubView.delegate = self
        self.view.addSubview(searchUserSubView)    
}
...
extension SearchContentViewController:SearchUserSubViewDelegate {
    
    func showProfileViewController(userObject:User, userProfileImage:UIImage) {
        let selectedUserController = STORYBOARD.instantiateViewController(withIdentifier: "selectedUserProfile") as! SelectedUserProfileViewController
        selectedUserController.userObject = userObject
        selectedUserController.userProfileImage = userProfileImage

        self.navigationController?.pushViewController(selectedUserController, animated: true)
    }
}

If you need more, please let me know.

Till now that is similar to what I wanted to show you if I knew there was `setupView()`.

So, what is the problem with your last code?

The problem with the code I put you above (last one) is that self.navigationController is nil.