Last active
February 26, 2022 05:46
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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