steipete / interposekit Goto Github PK
View Code? Open in Web Editor NEWA modern library to swizzle elegantly in Swift.
Home Page: https://interposekit.com/
License: MIT License
A modern library to swizzle elegantly in Swift.
Home Page: https://interposekit.com/
License: MIT License
To make swizzling more robust, it would be ideal if the return/argument types of the swizzled implementation could be checked against the original method.
As for how to do that… I guess the only way would be to accept an Objective-C method (via target/selector parameters) instead of an Objective-C block?
Quickly checked the code and I'm wondering ...
Global image watcher utilizes the globalWatcherQueue
queue to filter globalWatchers
:
But there's another place where this queue isn't used, access to globalWatchers
is not synced:
Additional thing is that the globalWatchers.append(self)
should be probably replaced by the InterposeWatcher.append(...)
to encapsulate this whole watching stuff (globalWatchers
).
Just a suggestion, perhaps you've thought of this and it won't work - I might be missing something.
Since the underlying implementation uses imp_implementationWithBlock
, the hooked function has a different type than the block you supply (notably no selector). Would it be possible to instead pass an IMP directly, and then it might be possible to make sure they both have the same type? (type check that the callAsFunction and the block you supply have the same type)
Example here although I haven't tested it with the calling convention requirements:
func genericFunction<T>(_ selName: String, _ callback: @escaping (String, T.Type) -> T) {
print("hi")
callback("foo", T.self)
}
func noop() {}
genericFunction("test") { (str, type) -> () -> Void in
print("Called with \(str)")
print(type)
return noop
}
This example passes the type into the method but you could potentially capture it into Task
itself/make Task generic.
EDIT: Oh I think I see the issue, it has to be a block if you want to be able to reference the task.
let object = NSURL.init(string: "https://www.google.com")!
let hook = try? object.hook(
#selector(getter: NSURL.host),
methodSignature: (@convention(c) (AnyObject, Selector) -> String).self,
hookSignature: (@convention(block) (AnyObject) -> String).self) { store in { `self` in
return "http://www.facebook.com"
}
}
let host = object.host
it's similar with this issue. steipete/Aspects#177
While my hooks work fine while debugging, they crash on device with the Release configuration. I think I've been able to nail it down to IKTAddSuperImplementationToClass
not being found. The dlsym in InterposeSubclass returns nil. Any ideas / tips for how to further debug this?
Hi there,
from example:
let hook = try testObj.hook( #selector(TestClass.sayHi), methodSignature: (@convention(c) (AnyObject, Selector) -> String).self, hookSignature: (@convention(block) (AnyObject) -> String).self) { store in {
self in return store.original(
self, store.selector) + "just this instance" } }
But i need to set hook with the following signature:
methodSignature: (@convention(c) (AnyObject, Selector, AnyObject, AnyObject, AnyObject) -> Void).self, { store in {
self in //to call the original method i need these three AnyObject values to pass. return store.original(
self, store.selector, ?, ?, ?) } }
How to access these three AnyObject ?
Thanks in advance.
_dyld_register_func_for_add_image
is called during dlopen
but before the Objective-C classes in the image are loaded. The effect of this is that the interposition(s) for a given class are run on the next dlopen
after the class is loaded. This may be too late depending on the interposition use case. Thoughts on clever ways to install a callback just after the Objective-C classes for a given image are loaded?
After adopting InterposeKit in my app, uploading a build to Apple fails when bitcode is enabled with the following error:
ITMS-90562: Invalid Bundle - The app submission can not be successfully recompiled from bitcode due to missing symbols during linking. You can try to reproduce and diagnose such issues locally by following the instructions from: https://developer.apple.com/library/archive/technotes/tn2432/_index.html
Uploading with bitcode disabled is fine. After reading the linked page I suspect it has something to do with the inline assembly in ITKSuperBuilder.m
. I removed InterposeKit from my app and uploaded with bitcode without error to confirm that it was indeed InerposeKit causing the issue. Please challenge my assumption if you think something else is the issue.
Do you think this can be fixed? At least I think it would make sense to document this limitation in the readme.
Class method crash
Trying to swizzle following:
`
do {
_ = try Interpose(CLLocationManager.self, builder: {
try $0.hook(#selector(getter: CLLocationManager.location),
methodSignature: (@convention(c) (AnyObject, Selector) -> CLLocation?).self,
hookSignature: (@convention(block) (AnyObject) -> CLLocation?).self) { store in {
`self` in
print("Before Interposing \(`self`)")
let originalLocation = store.original(`self`, store.selector) // free to skip
print("After Interposing \(`self`)")
return originalLocation
}
}
})
} catch {
print(error)
}
let classList = AppDelegate.getClassList().filter { class_conformsToProtocol($0, CLLocationManagerDelegate.self) }
for c in classList {
if !c.instancesRespond(to: #selector(CLLocationManagerDelegate.locationManager(_:didUpdateLocations:))) {
continue
}
do {
_ = try Interpose(c.self, builder: {
try $0.hook(#selector(CLLocationManagerDelegate.locationManager(_:didUpdateLocations:)),
methodSignature: (@convention(c) (AnyObject, Selector, [CLLocation]) -> ()).self,
hookSignature: (@convention(block) (AnyObject, Selector, [CLLocation]) -> ()).self) { store in {
print("Before Interposing")
print($0)
print($1)
print($2)
store.original($0, store.selector, $2) // free to skip
print("After Interposing \($0)")
}
}
})
} catch {
print(error)
}
}
`
Not able to figure out what is causing the issue.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.