Skip to content

Instantly share code, notes, and snippets.

@steipete
Last active October 17, 2020 14:00
Show Gist options
  • Save steipete/a18f767b4f88fb8c84486d8074081796 to your computer and use it in GitHub Desktop.
Save steipete/a18f767b4f88fb8c84486d8074081796 to your computer and use it in GitHub Desktop.
Helper to capture the last tapped bar button item in an UIKit or SwiftUI app. SwiftUI uses UIBarButtonItem under the hood in iOS 14 with the new toolbar API. Anchoring popovers from UIKit requires this as sender.
/// Helper to capture the last tapped bar button item in an UIKit or SwiftUI app.
final class BarButtonWatcher {
/// Singleton accessor. There can only be one currently tapped bar button item per process.
static let shared = BarButtonWatcher()
static private(set) weak var lastBarButtonItem: UIBarButtonItem? {
didSet {
// reset in next runloop
if lastBarButtonItem != nil {
DispatchQueue.main.async { self.lastBarButtonItem = nil }
}
}
}
init() {
_ = try? UIApplication.shared.hook(#selector(UIApplication.sendAction(_:to:from:for:)),
methodSignature: (@convention(c) (AnyObject, Selector, Selector, Any?, Any?, UIEvent?) -> Bool).self,
hookSignature: (@convention(block) (AnyObject, Selector, Any?, Any?, UIEvent?) -> Bool).self) {
store in { _self, action, target, sender, event in
if let barButtonItem = sender as? UIBarButtonItem {
BarButtonWatcher.lastBarButtonItem = barButtonItem
}
return store.original(_self, store.selector, action, target, sender, event)
}
}
}
}
@steipete
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment