Skip to content

Instantly share code, notes, and snippets.

@kibotu
Created June 5, 2026 09:39
Show Gist options
  • Select an option

  • Save kibotu/93a27d7108f521dfc2d6d360ad075b35 to your computer and use it in GitHub Desktop.

Select an option

Save kibotu/93a27d7108f521dfc2d6d360ad075b35 to your computer and use it in GitHub Desktop.
First Responder Logger for iOS to debug which view and their parent view controller has focus for iOS keyboard issues.
class FirstResponderLogger {
private static var isRunning : Bool = false
static func log(){
if (!FirstResponderLogger.isRunning) {
FirstResponderLogger.isRunning = true
Task {
while true {
try? await Task.sleep(nanoseconds: 1_000_000_000)
await MainActor.run {
if let firstResponder = UIResponder.current {
let address = String(format: "%p", Int(bitPattern: ObjectIdentifier(firstResponder)))
// Walk responder chain to find nearest VC
var next: UIResponder? = firstResponder.next
var parentVC: UIViewController?
while let responder = next {
if let vc = responder as? UIViewController {
parentVC = vc
break
}
next = responder.next
}
let vcName = parentVC.map { "\(type(of: $0))" } ?? "none"
Orchard.v("First Responder: \(vcName) - \(type(of: firstResponder))[\(address)]")
}
}
}
}
}
}
}
extension UIView {
var firstResponder: UIView? {
guard !isFirstResponder else { return self }
return subviews.lazy.compactMap { $0.firstResponder }.first
}
}
extension UIResponder {
private static weak var _firstResponder: UIResponder?
static var current: UIResponder? {
UIResponder._firstResponder = nil
UIApplication.shared.sendAction(
#selector(storeFirstResponder),
to: nil, from: nil, for: nil
)
return UIResponder._firstResponder
}
@objc private func storeFirstResponder() {
UIResponder._firstResponder = self
}
}
@kibotu

kibotu commented Jun 5, 2026

Copy link
Copy Markdown
Author

FirstResponderLogger.log()

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