Hook in CLLocationManagerDelegate protocol - delegates

I have a problem from 3 days :( I want to hook in CLLocationManagerDelegate protocol this method:
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
I tried everything but without success. I know how to hook into class or framework but I can't find a solution to hook a Delegate.
Please help me!
Thanks

Hooking requires you to provide objective-C class you would like to hook. This is what Class type is for. One way to get obj-c class is by name via objc_getClass function. But in your case as I understand it correctly you don't have the name. You want to hook every class that conforms to CLLocationManagerDelegate protocol and implements specific method. Here is what you can do.
You can obtain every registered obj-C class and search for those which conform toCLLocationManagerDelegate protocol like this:
static IMP original_didUpdateLocations;
void replaced_didUpdateLocations(id self, SEL _cmd, CLLocationManager* manager, NSArray* locations)
{
NSLog(#"%# did update locations to %#", manager, locations);
original_didUpdateLocations(self, _cmd, manager, locations);
}
...
#import <objc/runtime.h>
int numClasses = objc_getClassList(NULL, 0);
Class* list = (Class*)malloc(sizeof(Class) * numClasses);
objc_getClassList(list, numClasses);
for (int i = 0; i < numClasses; i++)
{
if (class_conformsToProtocol(list[i], #protocol(CLLocationManagerDelegate)) &&
class_getInstanceMethod(list[i], #selector(locationManager:didUpdateLocations:)))
{
MSHookMessageEx(list[i], #selector(locationManager:didUpdateLocations:), (IMP)replaced_didUpdateLocations, (IMP*)&original_didUpdateLocations);
}
}
free(list);
We need to know how many classes there is. objc_getClassList(NULL, 0) returns number of all registered classes.
Allocating memory with malloc(sizeof(Class) * numClasses) and filling it with objects of type Class using objc_getClassList(list, numClasses).
Searching through all these classes for those which conform to CLLocationManagerDelegate protocol and implement locationManager:didUpdateLocations: method. If we found one we are hooking it with our own implementation.
In our own implementation we are printing some debug message and calling original implementation before returning. Of course, you can do whatever you what, this is just an example.
Freeing allocated memory using free(list).

Related

Handling NSMenuDelegate menuWillOpen for changing targets

There are lots of related answers about using menuWillOpen. They all explain that one needs to set the menu's delegate first.
This is easy when I have just one target, like a Preferences window or the main application.
But what if I have a document based app, and I need to have the active document handle menuWillOpen? Then the delegate isn't a constant any more.
What's the proper way to handle this? Do I have to set the delegate to a single object (like the AppDelegate) and then forward the call to the active view controller (but how is that done correctly)? Or is there some other elegant way?
I came up with this code which appears to work:
// This is in my AppDelegate class, and the NSMenu's delegate points to it:
- (void)menuWillOpen:(NSMenu *)menu {
// Forward to active document controller
NSWindow *mainWindow = [NSApplication sharedApplication].mainWindow;
NSResponder *r = mainWindow.firstResponder;
while (r) {
if ([r respondsToSelector:_cmd]) {
[(id<NSMenuDelegate>)r menuWillOpen:menu];
return;
}
r = r.nextResponder;
}
}
It assumes that a controller down the responder chain implements menuWillOpen:

Select what methods from super class to Implement/Override in xcode

Is there a way to select/see what methods you can override/implement from the super class in xcode and have them created?
An example of what I mean is in Visual Studio you can select from a drop down at the top of the class file and if that method is not in your class it will get created.
In Android Studio you can right click on the class name/Generate/Override Methods and it brings up a list of the class methods that you can override.
Does such a thing exist in xcode so that I dont have to keep looking at the online documentation when I need to find something?
I understand what you're asking for well enough to know that this isn't exactly it however I couldn't pass up an opportunity get this very useful technique on "the stack(overflow)"! ;-) Add this method to any (NSObject sub-)class and it will log all unimplemented methods that the runtime is attempting to resolve against your class.
/*******************************************************************************
** Function - resolveInstanceMethod
**
** This is an AWESOME debugging method that allows you to see what methods
** the runtime is attempting to resolve against your class
********************************************************************************/
#ifdef DEBUG
+ (BOOL) resolveInstanceMethod:(SEL)sel {
BOOL result = [super resolveInstanceMethod:sel];
// comment out this next line if you want to
// log methods implemented by the super class
if (!result)
{
NSLog(#"Unimplemented Instance method: \'%s\'", sel_getName(sel));
}
return (result);
} /* resolveInstanceMethod: */
#endif // def DEBUG

Swift weak delegate runtime error (bad access). Bug?

I have a problem with delegates in Swift (OSX). I have a view, connected to a delegate through a weak reference. Simplified code could be like this:
protocol MyProtocol: class {
func protocolFunc() -> Int
}
class MyController : MyProtocol {
func protocolFunc() -> Int { return 2 }
}
class MyView : NSView {
weak var delegate: MyProtocol?
func grabData {
var data = delegate?.protocolFunc()
}
}
When delegate?.protocolFunc() is called, the app crashes saying "bad access". It's like if the MyController instance had disappeared... But it has not. The MyController instance lives in a NSDocument subclass; and view's delegate is properly set.
The crash goes away if I declare the delegate to be strong. But the thing is I want the delegate to be weak. What's going on? To my eyes, the weak reference should work.
At the time of writing (Xcode 6 Beta 5), there's a bug with weak delegates. For the time being, all you can do until it is fixed is to change protocol MyProtocol: class to #objc protocol MyProtocol and avoid using any pure Swift classes in your protocol.
A temporary alternate solution would be to change this:
weak var delegate: MyProtocol?
to this:
weak var delegate: MyController?
Of course it defeats the purpose of MyProtocol, however, it allows you to use pure Swift classes while we wait for a proper fix for this.

Obj-C Private Method Compiler Warnings

Private methods are a useful construct to keep code organised within class boundaries. An example being the organisation of long winded Quartz 2d instructions in a custom UIView subclass. I am able to include such methods in '.m' files with no declaration in '.h'. A working example from a UIView subclass '.m' file reads:
-(void)DoSomethingPrivate { //Not declared in interface
NSLog(#"Does this print a private function?");
}
- (id)initWithFrame:(CGRect)frame //Declared in inherited interface
{
self = [super initWithFrame:frame];
if (self) {
[self DoSomethingPrivate]; //Error: 'Instance method not found'
} //... but it works anyway.
return self;
}
My problem is that the compiler generates the warning "Instance method '-DoSomethingPrivate' not found (return type defaults to 'id')" on the line calling the private function. I'm aware from responses to this question that I can use a 'no name' interface category to 'hide' private method declarations.
However, when I review Apple sample code SimpleStocks, file "SimpleStockView.m", it contains a private function which is neither declared in a no-name category interface, nor does it generate compiler warnings:
//Private Function
- (void)drawRadialGradientInSize:(CGSize)size centeredAt:(CGPoint)center {
...
}
//Is called by this function...
- (UIImage *)patternImageOfSize:(CGSize)size {
...
//The next line doesn't generate any warnings!
[self drawRadialGradientInSize:size centeredAt:center];
...
}
I'd be grateful if anyone can shed any light on how Apple's sample-code private-methods appear to escape compiler checks, so I may avoid having to maintain a 'no-name' category header with all my private methods.
Many thanks.

Monotouch: understand the delegate mechanism pattern

I didin't completely understand the delegate mechanism in monotouch. Can anyone help me to understand this concept?
The question is simple. I'll try to map what I've done in Objective C in Monotouch.
For example, suppose I've creating a UIPopoverController in Objective C inside MyController. In Objective C the code is the following:
#interface MyController : UIViewController <UIPopoverControllerDelegate> {
// ...
}
// ...
#end
Inside MyController I can istantiate a UIPopoverController like the following:
UIPopoverController *popover = // ...
popover.delegate = self;
and finally methods used in the delegate.
So, what about Monotouch?
Through this code I can istantiate the UIPopoverController inside MyController class that extends UIViewController inside a specific TouchUpInside event handler:
popover = new UIPopoverController(new CustomController());
popover.PopoverContentSize = new SizeF(200f, 200f);
popover.PresentFromRect(button.Frame, containerForButtonView, UIPopoverArrowDirection.Left, true);
P.S. An important aspect is to put popover reference as a member class and not as a local variable inside the handler because the monotouch GC works well!!!
Thank you in advance.
This really has more to do with C# than MonoTouch itself. In MonoTouch, UIPopoverControllerDelegate is a class, and C# doesn't allow multiple inheritance, so you can't translate code one to one with Obj-C. There's an easier way out though (code below compiles, but obviously doesn't work):
public class MyController: UIViewController {
public void mymethod(){
var popover = new UIPopoverController();
popover.DidDismiss += HandlePopoverDidDismiss;
popover.PopoverContentSize = new SizeF(200f, 200f);
popover.PresentFromRect(button.Frame, containerForButtonView, UIPopoverArrowDirection.Left, true);
}
void HandlePopoverDidDismiss (object sender, EventArgs e)
{
Console.WriteLine("Working!");
}
}
}
As you can see, you can add an event handler to to the DidDismiss event in the popover, which will do what you want. In general, all events that in Obj-C are handled by the delegate in all controls can be used this way. You can also write the method inline, like this:
popover.DidDismiss += delegate {
//dosomething
};
Hope this is what you're looking for.
This doesn't answer your question specific to your UIPopovercontroller I think you will find this link from the Monotouch Docs useful. It explains the differences between Objective-C delegates and C# delegates with relation to Monotouch. With regards to your specific problem, I havent got time to whip up a quick test case to understand it fully but figured I'd post that link so you've got something to read in the mean time!

Resources