Skip to content

Instantly share code, notes, and snippets.

@Nillerr
Last active February 26, 2022 05:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nillerr/aa972e7064d1ee0e143597ca472ee39d to your computer and use it in GitHub Desktop.
Save Nillerr/aa972e7064d1ee0e143597ca472ee39d to your computer and use it in GitHub Desktop.
Replaces a call to *addSubview* with an implementation that ensures it is always invoked on the main thread.
import UIKit
/**
Swizzles `addSubview` of `UIView`, replacing it with an implementatio that ensures it is always
invoked on the main thread.
Call this method in your application entry point, e.g. the `UIApplicationDelegate`.
*/
func swizzleAddSubview() {
let clazz = UIView.self
let method: Method = class_getInstanceMethod(clazz, #selector(UIView.addSubview(_:)))
let swizzled: Method = class_getInstanceMethod(clazz, #selector(UIView.addSubviewOnMainThread(_:)))
method_exchangeImplementations(method, swizzled)
}
extension UIView {
/**
Forwards a call to `addSubview` on the main thread. If this method is called on the main
thread, it will call `addSubview` immediately. If it is invoked on another thread, it will
dispatch a call to `addSubview` on the main thread using GCD.
- Parameter view: Child view to add
*/
@objc dynamic func addSubviewOnMainThread(view: UIView) {
// Since we've replaced the method signature of `addSubview` with this one, it means that
// to access the original `addSubview`, we must call `addSubviewOnMainThread`, because
// the two implementations swapped names.
if (NSThread.isMainThread()) {
addSubviewOnMainThread(view)
} else {
dispatch_sync(dispatch_get_main_queue()) {
self.addSubviewOnMainThread(view)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment