Search code examples
iosswiftuinavigationcontroller3dtouch

3D Touch Peek/Pop with Navigation Controller


This question is somewhat related to my other question from here

Out of Apple's Sample Code, I have following code for 3D Touch Peek & Pop:

func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
    guard let indexPath = tableView.indexPathForRow(at: location) else { return nil }

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let viewController = storyboard.instantiateViewController(withIdentifier: ChatDetailViewController.identifier)
    guard let chatDetailViewController = viewController as? ChatDetailViewController else { return nil }

    chatDetailViewController.chatItem = chatItem(at: indexPath)
    let cellRect = tableView.rectForRow(at: indexPath)
    previewingContext.sourceRect = previewingContext.sourceView.convert(cellRect, from: tableView)
    chatDetailViewController.isReplyButtonHidden = true

    let navigationController = UINavigationController(rootViewController: viewController
    return navigationController
}

func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {

    self.navigationController!.show((viewControllerToCommit as! UINavigationController).viewControllers[0], sender: self)
}

So, in Peek, I am wrapping the view controller just got created in a new navigation controller and returning it self:

let navigationController = UINavigationController(rootViewController: viewController
return navigationController

However, in Pop, I have to discard the navigation controller created above and 'show' it within the navigation controller I am currently in.

Why This Way?

I wanted to show a top bar within 'Peek' (again, as discussed here). However, if I just commit the same navigation controller that was newly created, it takes away all the other attributes, such as back button, custom push/pop animations, ect. So, when the view controller is 'Pop'ed (committed), I have to extract it and put it back inside the current navigation controller I am within.

Issue

Above code works perfectly. However, I am leaving the navigation controller I made inside of Peek to get leaked. Also, when I test of leaks, it goes show a small memory leak. How would I release/deallocate the navigation controller I am leaving behind in 'Pop'?


Solution

  • There is no "leak" in what you're doing.

    • The view controller returned from viewControllerForLocation is retained by the runtime while the user is peeking, and is released when the user stops peeking.

    • The view controller shown in commit is an ordinary shown view controller and is retained by the runtime as part of the view controller hierarchy. It is released when you unwind from that view controller (dismiss or pop) in the usual way.