Skip to content

Instantly share code, notes, and snippets.

@avaidyam
Created March 11, 2018 19:53
Show Gist options
  • Save avaidyam/ce878e8165ab624d09ef0ea1dc517bc5 to your computer and use it in GitHub Desktop.
Save avaidyam/ce878e8165ab624d09ef0ea1dc517bc5 to your computer and use it in GitHub Desktop.
An attempt at creating a subclass of an unknown/hidden NSProxy type.
func test() {
// Allocate a new class-pair from an unknown superclass type.
let selector = Selector(("doStuff"))
let oldClass_: AnyClass = Something.self
let newClass_: AnyClass = objc_allocateClassPair(NSClassFromString("_NSObjectAnimator"), "MyNewClass", 0)!
// Copy instance and class methods over.
let m = class_getInstanceMethod(oldClass_, selector)!
class_addMethod(newClass_, selector, method_getImplementation(m), method_getTypeEncoding(m))
objc_registerClassPair(newClass_);
// Required to avoid +isSubclassOfClass: failure due to NSProxy types.
let oldClass = unsafeBitCast(oldClass_, to: NSObject.Type.self)
let newClass = unsafeBitCast(newClass_, to: NSObject.Type.self)
// Test the newly cloned subclass!
print("old!")
_ = oldClass.perform("alloc").takeUnretainedValue().perform(Selector(("initWithTarget:"))).takeUnretainedValue().perform(selector)
print("new!")
_ = newClass.perform("alloc").takeUnretainedValue().perform(Selector(("initWithTarget:"))).takeUnretainedValue().perform(selector)
}
@objc public class Something: NSObject {
@objc(initWithTarget:)
public init(_ target: Any) {
super.init()
print("**** INIT \(target) ****")
}
@objc public func doStuff() {
print("\(type(of: self)) stuff done!")
}
}
@_silgen_name("objc_alloc")
private func objc_alloc(_ cls: AnyClass!) -> AnyObject!
/*
old!
**** INIT 2001-01-01 00:00:00 +0000 ****
Something stuff done!
new!
MyNewClass stuff done!
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment