Instead of while loops, we could use recursion (please note that none of the following code is thoroughly tested):
// Swift 2.3
public extension UIViewController {
    public var topViewController: UIViewController {
        let o = topPresentedViewController
        return o.childViewControllers.last?.topViewController ?? o
    }
    public var topPresentedViewController: UIViewController {
        return presentedViewController?.topPresentedViewController ?? self
    }
}
On the more general issue of traversing the view controller hierarchy, a possible approach is to have two dedicated sequences, so that we can:
for ancestor in vc.ancestors {
    //...
}
or:
for descendant in vc.descendants {
    //...
}
where:
public extension UIViewController {
    public var ancestors: UIViewControllerAncestors {
        return UIViewControllerAncestors(of: self)
    }
    public var descendants: UIViewControllerDescendants {
        return UIViewControllerDescendants(of: self)
    }
}
Implementing ancestor sequence: 
public struct UIViewControllerAncestors: GeneratorType, SequenceType {
    private weak var vc: UIViewController?
    public mutating func next() -> UIViewController? {
        guard let vc = vc?.parentViewController ?? vc?.presentingViewController else {
            return nil
        }
        self.vc = vc
        return vc
    }
    public init(of vc: UIViewController) {
        self.vc = vc
    }
}
Implementing descendant sequence: 
public struct UIViewControllerDescendants: GeneratorType, SequenceType {
    private weak var root: UIViewController?
    private var index = -1
    private var nextDescendant: (() -> UIViewController?)? // TODO: `Descendants?` when Swift allows recursive type definitions
    public mutating func next() -> UIViewController? {
        if let vc = nextDescendant?() {
            return vc
        }
        guard let root = root else {
            return nil
        }
        while index < root.childViewControllers.endIndex - 1 {
            index += 1
            let vc = root.childViewControllers[index]
            var descendants = vc.descendants
            nextDescendant = { return descendants.next() }
            return vc
        }
        guard let vc = root.presentedViewController where root === vc.presentingViewController else {
            return nil
        }
        self.root = nil
        var descendants = vc.descendants
        nextDescendant = { return descendants.next() }
        return vc
    }
    public init(of vc: UIViewController) {
        root = vc
    }
}