Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method swizzling a private framework iOS API

I know there are countless resources on method swizzling. However is it possible to swizzle a method from a private API? The problem is that there are no header files. I would like to swizzle a method from a private class in a PrivateFramework such as (random example) Message.framework methods

This is for personal testing, I understand that it will get rejected to oblivion by Apple.

like image 487
John Smith Avatar asked Jun 27 '14 00:06

John Smith


People also ask

What is method swizzling in IOS?

Method swizzling is the process of replacing the implementation of a function at runtime. Swift, as a static, strongly typed language, did not previously have any built-in mechanism that would allow to dynamically change the implementation of a function.

How does method swizzling work?

Method swizzling is the process of changing the implementation of an existing selector. It's a technique made possible by the fact that method invocations in Objective-C can be changed at runtime, by changing how selectors are mapped to underlying functions in a class's dispatch table.

How do I disable method swizzling?

Method swizzling in Firebase Cloud Messaging Developers who prefer not to use swizzling can disable it by adding the flag FirebaseAppDelegateProxyEnabled in the app's Info. plist file and setting it to NO (boolean value).


1 Answers

You can use NSClassFromString to get Class and use runtime library to perform method swizzling. No header files required. You just need to know class name and method signature.

sel_getUid can be used when @selector(somePrivateMethod) give your error about somePrivateMethod is not valid selector (because header is not available)

Code taken from my Xcode plugin

SEL sel = sel_getUid("codeDiagnosticsAtLocation:withCurrentFileContentDictionary:forIndex:");
Class IDEIndexClangQueryProviderClass = NSClassFromString(@"IDEIndexClangQueryProvider");

Method method = class_getInstanceMethod(IDEIndexClangQueryProviderClass, sel);
IMP originalImp = method_getImplementation(method);

IMP imp = imp_implementationWithBlock(^id(id me, id loc, id dict, IDEIndex *idx) {
    id ret = ((id (*)(id,SEL,id,id,id))originalImp)(me, sel, loc, dict, idx);

    // do work

    return ret;
});

method_setImplementation(method, imp);
like image 156
Bryan Chen Avatar answered Nov 15 '22 22:11

Bryan Chen