A common situation in Cocoa when dealing with view controllers is setting a property (frequently a custom delegate) on a destination view controller in prepareForSegue:sender:. In Objective-C, the destinationViewController is of type id, so we need to first introspect the destinationViewController's class. If it's the class we want, we then create a local variable and then cast it with our desired class. Once we have that casted variable, we can set our delegate:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"segueToSecondViewController"]) {
        if ([segue.destinationViewController isKindOfClass:[SecondViewController class]]) {
            SecondViewController *secondVC = (SecondViewController *)segue.destinationViewController;
            secondVC.delegate = self;
        }
    }
}

Let's explore this in Swift:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
}

One issue is that segue.identifier is an optional, so here we could use optional binding:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let segueIdentifier = segue.identifier {
    }   
}

Next, we can switch on the value of the identifier:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let segueIdentifier = segue.identifier {
        switch segueIdentifier {
        case "segueToSecondViewController": break // TODO: Set delegate here
        default: break
        }
    }
}

It's a bit cleaner though to use pattern matching and remove the if let. A Swift Optional is actually an enum that has a None and a Some case with a generic associated value. Here we match on our desired associated identifier:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    switch segue.identifier {
    case (.Some("segueToSecondViewController")): break // TODO: Set delegate here
    default: break
    }
}

Now we need to grab the destinationViewController with an optional downcast and set the delegate:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    switch segue.identifier {
    case (.Some("segueToSecondViewController")):
        let secondVC = segue.destinationViewController as? SecondViewController
        secondVC?.delegate = self
        // Handle any other necessary configuration
    default: break
    }
}

Another approach would be to focus on the segue.destinationViewController. Depending on the situation, we may not care about the segue.identifier; each of our segues may be to view controllers of unique classes. In Swift, the destinationViewController is of type AnyObject. So, we can perform an optional downcast into a constant, and then we can set the delegate and handle any other necessary configuration that we may need using optional chaining. We can also add similar code for configuring other destinationViewControllers:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    let secondVC = segue.destinationViewController as? SecondViewController
    secondVC?.delegate = self

    let thirdVC = segue.destinationViewController as? ThirdViewController
    thirdVC?.title = "Hi Mom!"
}

Or to simplify, if we only have one possible segue for this scenario in our app, we can combine the optional downcast and delegate setting:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    (segue.destinationViewController as? SecondViewController)?.delegate = self
}