Skip to content

Instantly share code, notes, and snippets.

@ruby109
Last active January 7, 2021 06:05
Show Gist options
  • Save ruby109/934b28462b30ef75f238b80de1cb8544 to your computer and use it in GitHub Desktop.
Save ruby109/934b28462b30ef75f238b80de1cb8544 to your computer and use it in GitHub Desktop.
Long press custom back button to show navigation history
struct Zip3Generator
<
A: IteratorProtocol,
B: IteratorProtocol,
C: IteratorProtocol
>: IteratorProtocol {
private var first: A
private var second: B
private var third: C
private var index = 0
init(_ first: A, _ second: B, _ third: C) {
self.first = first
self.second = second
self.third = third
}
// swiftlint:disable large_tuple
mutating func next() -> (A.Element, B.Element, C.Element)? {
if let first = first.next(), let second = second.next(), let third = third.next() {
return (first, second, third)
}
return nil
}
}
func zip<A: Sequence, B: Sequence, C: Sequence>(_ first: A, _ second: B, _ third: C) -> IteratorSequence<Zip3Generator<A.Iterator, B.Iterator, C.Iterator>> {
return IteratorSequence(Zip3Generator(first.makeIterator(), second.makeIterator(), third.makeIterator()))
}
public protocol CustomBackButtonProtocol {
}
extension CustomBackButtonProtocol where Self: UIViewController {
@available(iOS 13.0, *)
func setupMenu() -> UIMenu {
guard let titles = self.navigationController?.viewControllers.map({ $0.title }).dropLast(),
let backButtonTitles = self.navigationController?.viewControllers.map({ $0.navigationItem.backButtonTitle }).dropLast(),
let navigationItemTitles = self.navigationController?.viewControllers.map({ $0.navigationItem.title }).dropLast(),
titles.count == backButtonTitles.count,
titles.count == navigationItemTitles.count else {
assertionFailure("titles and backbuttonTitles should not be nil")
return UIMenu()
}
let actionTitles = zip(titles, backButtonTitles, navigationItemTitles).map{ (title, backButtonTitle, navigationItemTitle) -> String in
if backButtonTitle != nil {
return backButtonTitle!
}
if title == nil, navigationItemTitle == nil {
return ""
}
if title == nil, navigationItemTitle != nil {
return navigationItemTitle!
}
if title != nil, navigationItemTitle == nil {
return title!
}
if let title = title, let navigationItemTitle = navigationItemTitle {
if title == navigationItemTitle {
return title
} else {
return navigationItemTitle
}
}
return ""
}
let actions = actionTitles.enumerated().map{ (index, actionTitle) -> UIAction in
let action = UIAction(title: actionTitle) { [weak self] (_) in
guard let viewControllerArray = self?.navigationController?.viewControllers else {
self?.navigationController?.popToRootViewController(animated: true)
return
}
let viewController = viewControllerArray[index]
self?.navigationController?.popToViewController(viewController, animated: true)
}
return action
}
let menu = UIMenu(title: "", image: nil, identifier: nil, options: .displayInline, children: actions.reversed())
return menu
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment