Skip to content

Instantly share code, notes, and snippets.

@Lobster-King
Forked from michaeleisel/ANRChecker.swift
Created January 12, 2021 13:44
Show Gist options
  • Save Lobster-King/9a2b838ca9fe6bb9981dd2cb67d00f30 to your computer and use it in GitHub Desktop.
Save Lobster-King/9a2b838ca9fe6bb9981dd2cb67d00f30 to your computer and use it in GitHub Desktop.
// Note that this checker is always running, even when the app is in the background (where it doesn't matter if the main thread is blocked)
// You'll have to add more code if you don't want the checker to run while the app is in the background
final class ANRChecker {
private let ANRThreshold: CFTimeInterval = 5
// This variable may be accessed from multiple threads at the same time. It won't cause issues, but if you want prevent the thread sanitizer from complaining, you can add locking around it or w/e
private lazy var lastResponseTime: CFTimeInterval = CACurrentMediaTime()
func beginChecking() {
updateLastResponseTime()
checkLastResponseTime()
}
private func updateLastResponseTime() {
lastResponseTime = CACurrentMediaTime()
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.updateLastResponseTime()
}
}
private func checkLastResponseTime() {
crashIfDelayTooLarge()
DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + 1) {
self.checkLastResponseTime()
}
}
private func crashIfDelayTooLarge() {
let delay = CACurrentMediaTime() - self.lastResponseTime
if delay > self.ANRThreshold {
fatalError()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment