How to swizzle AudioSessionAddPropertyListener - ios

There is a library in my project that is adding audio property listeners. I really need to be able to block it from doing so, but I don't have the source code.
I've done a swizzle before for the addObserver method in NSNotificationCenter. Could you help me do the same for AudioSessionAddPropertyListener? If the method trying to be added in the call does not match my whitelist, I want to block it. Otherwise, I'll call the original method.
I don't know what class for which I should overload the load function. I'm looking inside of
Audio.h. I'm adding some pseudo/real/badlyNamed code so you can see what I'm trying to do.
#import <AudioToolbox/AudioToolbox.h>
#interface AuidoClassUmm (SOMETHING)
#end
+ (void) load
{
Method original, swizzled;
original = class_getInstanceMethod(self, #selector(AudioSessionAddPropertyListener:selector:name:object:));
swizzled = class_getInstanceMethod(self, #selector(swizzled_AudioSessionAddPropertyListener:selector:name:object:));
method_exchangeImplementations(original, swizzled);
}
-(void) swizzled_AudioSessionAddPropertyListener:selector:name:object:
{
if(//funciton object I don't like)
{
return;
}
else
{
// Calls the original addObserver function
[self swizzled_AudioSessionAddPropertyListener::notificationObserver selector:notificationSelector name:notificationName object:notificationSender];
}
}

AudioSessionAddPropertyListener() is a C function, not an Objective-C method. You can't swizzle it.
(Even if you could swizzle it, that would almost certainly be a bad idea.)

Related

How to implement function to pointer in swift

#import "ViewController.h"
#interface ViewController ()
//Declare block as property
#property (nonatomic, strong) void (^dataBlock)(BOOL success);
#end
#implementation ViewController
- (void) myMethod1:(void (^)(BOOL success))response {
//Here data block holds the reference to response block
_dataBlock = response;
}
- (void) myMethod2 {
//Check for _dataBlock and invoke it.
if (_dataBlock) {
_dataBlock(YES);
}
}
- (IBAction) buttonClick {
//Call for myMethod1 and call back block is invoked in myMethod2
[self myMethod1:^(BOOL success) {
if (success) {
NSLog(#"Im Done");
}
}];
}
#end
Above sample is my code in Objective-C
Callback Block of "myMethod1"(response) is having reference/stored to "dataBlock" Property.
then invoke "dataBlock" from "myMethod2".
since "datablock" have reference to"myMethod1" block named "response", i'll be getting call back in "myMethod1", please look at the code snippet (similar to function to pointer).
same thing i want to implement in swift. I have tried implementing this in swift using closures, but not getting it.
No, there is not, unless it's on a Jailbroken device.
Apple does not let 3rd party apps alter the core behavior of the phone.
Now you could put the phone in a Faraday cage and put antennas on the inside and outside, and disconnect them when you wanted to block calls.
Actually you sort of can, but not really programmatically from iOS. If the BLE device implements the HID profile then you can simulate a double click on the lock button which would dismiss the call. I have done that, but it is a bit of a clunky solution.

How can I access the object on which a category method was called?

I'm using #implementation to add a new function to UIView.
#implementation UIView (test)
- (void)newFunction {
}
#end
Now, in the newFunction I want to "grab" the object (UIView) that was used when calling the function.
For example when I call newFunction within viewDidLoad
- (void)viewDidLoad {
[myView newFunction];
}
I want the newFunction to know what object was used to make the call (in this case, myView).
A simple solution would be to pass it along when making the call ([myView newFunction:myView]), but that is not what I am looking for.
I looked at Apple's documentation on the subject, but didn't really find an answer to my question.
#import "UIView+UIView_Category.h"
#implementation UIView (UIView_Category)
- (void)newFunction
{
NSLog(#"Object = %#",self);
}
#end
What you describe is called a category (not #implementation). It is an extension to the UIView class (in this case).
Generalcally:
#implementation __CLASS_TO_EXTEND__ (__CATEGORY_NAME__)
The category, as it is an extension, is the instance that you call the method on. So, you use self as you usually would to access the current instance.

How to make method having executable block as a argument which should execute on completion of the method in objective c

I want to define the method which will contain the block as an argument but block should be run on the completion of the method.
For Example:
[picker dismissViewControllerAnimated:YES completion:^{
imageThumb = pickedImage;
imageViewThumb.image = imageThumb;
}];
Please have a look what i did yet.
I declared the method in .h file-
-(void)resizeImageForSmoothness: (int) imageSmoothness completion: (void (^)(void))completion;
I implemented it in .m file-
-(void)resizeImageForSmoothness:(int)imageSmoothness completion: (void (^)(void))completion
{
// Here i performed my image resizing activity
}
How can my code will know that method has been completed and then run the completion block?
How can we declare and define such method?
How to store the block depends on how you do your stuff. If it's a synchronous operation (that is, the method blocks until whole operation is complete) you simply call it like a function:
- (void)fooWithHandler:(void(^)())handler
{
// Do things.
handler();
}
If the operation is asynchronous, you might want to store the block in a variable or even a dictionary. In this case you need to copy the block. You can either do this via the low-level Block_copy and Block_release C functions, but you can also treat a block like an Objective-C object! (Xcode doesn't provide autocompletion for this, for some reason.)
#interface MyClass {
void (^myHandler)();
}
- (void)fooWithHandler:(void(^)())handler
#end
#implementation MyClass
- (void)fooWithHandler:(void(^)())handler
{
myHandler = [handler copy];
// Do things.
// Then, when you're done (this is probably in another method):
if (myHandler) {
myHandler();
myHandler = nil;
}
}
#end
You can do something like that and use the return type et parameter you might need :
- (void)doStuffAndExecute:(void (^)(void))handler
{
// do stuff
handler();
}

Add additional behavior to method without subclassing

I need to add additional behavior to methods I need to extend, i.e. implement method that looks like
- (void)extendMethod:(SEL)selector forClass:(Class)class withCompletionBlock:(void (^)(void))completionBlock;
So every time Class instance call a method with SEL selector in addition should be invoked my completion block.
I've tried method swizzling, but ran into some problems: I want original method implementation to be called.
What I need is very similar with subclassing, but this should be implemented without subclassing.
UPDATE:
For example I have subclass of UIViewController named MyViewController. MyViewController have - (void)viewDidLoad method. Somewhere in application I call method
[methodExtender extendMethod:#selector(viewDidLoad)
forClass:[MyViewController class]
withCompletionBlock:^{
NSLog(#"view did load called");
}];
So after viewDidLoad method of every instance of MyViewController my completion block invoked.
I'm not sure how you want to use selector, but you can try extend any class(even ones that you don't have implementation file) by using mechanism in Objective-C know as "Categories".
From Xcode click on File->New->File (command+n)
From Cocoa Touch choose Objective-C category
Type name of your category and choose class on which you want to make category (I choosed UIButton)
Then next and Create.
Xcode will create two files for example: UIButton+extendMethod.h
Declare your method in header file and implement it in *.m file.
Using
If you want to use in let's say your View Controller in *.h file import
#import "UIButton+extendMethod.h"
and then you can call your method like this:
UIButton *button = [[UIButton alloc] init];
[button extendMethod:#selector(yourMethod:)];
Swizzling does allow you to call the original implementation, though it is just a bit confusing. Because the implementations are swapped after swizzling, you call the original implementation using the selector of the swizzled method:
- (void)mySwizzledImplementation {
// do stuff
// now call original implementation (using swizzled selector!)
[self mySwizzledImplementation];
// do more stuff
}
See also http://cocoadev.com/wiki/MethodSwizzling
There is no way (anymore)to simulate inheritance without subclassing. There use to be Posing, method swizzling is all that is left (not as elegant as posing though). Here is one way to do method swizzling correctly while being able to call the original implementation.
int swizzle_instance_methods(Class class, SEL selector, IMP replacement, IMP *store) {
#synchronized(class) {
Method method = class_getInstanceMethod(class, selector);
IMP original_imp = NULL;
if (method != NULL) {
const char *type = method_getTypeEncoding(method);
IMP original_imp = class_replaceMethod(class, selector, replacement, type);
if (original_imp == NULL)
original_imp = method_getImplementation(method);
if (original_imp != NULL && store != NULL) {
*store = original_imp;
}
}
return (original_imp != NULL);
}
}
+ (void) load
{
static IMP originalMethodImpl = NULL;
IMP customMethodImpl = imp_implementationWithBlock(^(id self_) {
NSString *descr = ((NSString(*)(id,SEL))originalMethodImpl)(self_, #selector(description);
return [NSString stringWithFormat:#"<--- %# --->",descr];
});
swizzle_instance_methods([self class], #selector(description), customMethodImpl, &originalMethodImpl);
}
I might add that this is nice for debugging and I think that it can be greate for building excellent frameworks. Alas, Apple seems to think differently and using method swizzling can result in your app being excluded from the App store. If you are not aiming for the app store then all the power to you.
It is be possible with ObjC categories. For ex, you can extend hasPrefix method of NSString as follows,
-(BOOL)hasPrefixx:(NSString *)aString
{
NSLog(#"Checking has prefix");
return [self hasPrefix:aString];
}
If you import the category, you should be able to call this method. But his means you got change the method in your call.
By the way, Method swizzling should work. Bit of explanation here.

Swizzling and super

I am trying to swizzle the canPerformAction:withSender: method for UIResponder and all its subclasses which have overridden this method.
I am doing this by storing the original implementations in a dictionary keyed by class name; and looking up the dictionary in the swizzled version of the implementation before calling out to the original implementation.
This seems to work fine for some cases, but fails when the original implementation calls out to super. Then my swizzled method continuously keeps getting invoked and the program gets into infinite recursion.
What could be wrong here?
After the swizzle the -original with -custom:
-(void)custom {
[self custom]; // calls -original
}
-(void)original {
[self original]; // calls -custom
}
Said that, if you have the methods swizzled in the superclass, objc_msgSendSuper will do the same: call original for custom and versa giving you the recursion.
-(void)custom {
[self original]; // calls -custom, makes recursion
}
-(void)original {
[self custom]; // calls -original, makes recursion
}

Resources