Skip to content

Instantly share code, notes, and snippets.

@rolfbjarne
Created November 30, 2015 16:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rolfbjarne/1115b3e1aa14ee7acfd2 to your computer and use it in GitHub Desktop.
Save rolfbjarne/1115b3e1aa14ee7acfd2 to your computer and use it in GitHub Desktop.
using System;
using System.Runtime.InteropServices;
using ObjCRuntime;
using UIKit;
using runtime;
namespace hook
{
public static class Hook
{
[DllImport("/usr/lib/libobjc.dylib")]
private static extern IntPtr class_getInstanceMethod(IntPtr classHandle, IntPtr Selector);
[DllImport("/usr/lib/libobjc.dylib")]
private static extern IntPtr method_getImplementation(IntPtr method);
[DllImport("/usr/lib/libobjc.dylib")]
private static extern void method_setImplementation(IntPtr method, IntPtr imp);
[DllImport ("/usr/lib/libobjc.dylib")]
internal static extern IntPtr object_getClass (IntPtr obj);
[MonoNativeFunctionWrapper]
private delegate IntPtr PopDelegate(IntPtr self, IntPtr sel, bool animated);
private static IntPtr OrigPopImpl;
static PopDelegate popDelegate;
public static void Setup ()
{
var classHandle = Class.GetHandle("UINavigationController");
var selector = Selector.GetHandle("popViewControllerAnimated:");
var method = class_getInstanceMethod(classHandle, selector);
OrigPopImpl = method_getImplementation (method);
popDelegate = PopViewControllerAnimated;
var imp = Marshal.GetFunctionPointerForDelegate (popDelegate);
method_setImplementation(method, imp);
}
[MonoPInvokeCallback(typeof (PopDelegate))]
private static IntPtr PopViewControllerAnimated (IntPtr self, IntPtr sel, bool animated)
{
// When built for simulator this line returns UINavigationController instance
// When build for device with project iOS build setting 'Enable Device Specific Builds' enabled
// line also returns UINavigationController.
// When build for device with this setting turned off this line returns instance
// of __NSMallocBlock__ and subsequent call passing parameters on to original
// selector method crashes
// This is not specific to the selector chosen for this harness and the marshalling issues
// are seen in all cases that have been tried. In our production code we are hooking a number
// of selectors on several classes. The solution works for all but the build configuration
// outlined above.
Console.WriteLine ("PopViewControllerAnimated (self: {0} selector: {1} animated: {2})", new Class (object_getClass (self)).Name, Selector.FromHandle (sel).Name, animated);
var navigationController = ObjCRuntime.Runtime.GetNSObject<UINavigationController>(self);
Console.WriteLine ("navigationController: {0}", navigationController);
var del = (PopDelegate) Marshal.GetDelegateForFunctionPointer (OrigPopImpl,typeof(PopDelegate));
return del (self, sel, animated);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment