ajrlewis
ajrlewis

Reputation: 3058

iOS New-Contact-Style Segue in Swift

I am trying to emulate the iOS contacts segueing between two view controllers.

I have a simple Person class given by:

class Person {
    var name = ""
}

and a UIViewController that contains an array of Person, which is embedded in a UINavigationController:

class PeopleViewController: UIViewController {

    var people = [Person]()
    var selectedPerson: Person?

    switch segueIdentifier(for: segue) {
    case .showPerson:
        guard let vc = segue.destination as? PersonViewController else { fatalError("!") }
        vc.person = selectedPerson 
    }

}

This controller uses a Show segue to PersonViewController to display the selectedPerson:

class PersonViewController: UIViewController {
    var person: Person!
}

PeopleViewController can also add a new Person to the array of Person. The NewPersonViewController is presented modally, however:

class NewPersonViewController: UIViewController {
    var person: Person?
}

If a new Person is added, I want NewPersonViewController to dismiss but show the new Person in the PersonViewController that is part of the navigation stack. My best guess for doing this is:

extension NewPersonViewController {
    func addNewPerson() {
        weak var pvc = self.presentingViewController as! UINavigationController
        if let cvc = pvc?.childViewControllers.first as? PeopleViewController {
            self.dismiss(animated: false, completion: {
                cvc.selectedPerson = self.person
                cvc.performSegue(withIdentifier: .showPerson, sender: nil)
            }
        }
    }
}

However, (1) I'm not too happy about forcing the downcast to UINavigationController as I would have expected self.presentingViewController to be of type PeopleViewController? And (2), is there a memory leak in the closure as I've used weak var pvc = self.presentingViewController for pvc but not for cvc? Or, finally (3) is there a better way of doing this?

Many thanks for any help, suggestions etc.

Upvotes: 0

Views: 45

Answers (1)

k-thorat
k-thorat

Reputation: 5123

(1) I'm not too happy about forcing the downcast to UINavigationController as I would have expected self.presentingViewController to be of type PeopleViewController?

There is nothing wrong in downcasting. I would definitely remove force unwrapping.

(2), is there a memory leak in the closure as I've used weak var pvc = self.presentingViewController for pvc but not for cvc?

I think, there is none.

(3) is there a better way of doing this?

You can present newly added contact from NewContactVC. When you about to dismiss, call dismiss on presentingVC.

// NewPersonViewController.swift
func addNewPerson() {
// New person is added
// Show PeopleViewController modally
}

Note: Using presentingViewController this way will dismiss top two/one Modal(s). You will see only top view controller getting dismissed. If you can't determine how many modals going to be, you should look-into different solution or possibly redesigning navigation flow.

// PeopleViewController.swift
func dismiss() {
    if let presentingVC = self.presentingViewController?.presentingViewController {
       presentingVC.dismiss(animated: true, completion: nil)
    } else {
       self.dismiss(animated: true, completion: nil)
    }
}

Upvotes: 0

Related Questions