How to Port "Method_Getimplementation" and "Method_Setimplementation" to Monotouch

How to port method_getImplementation and method_setImplementation to MonoTouch?

This looks like a good candidate for us to provide a general purpose mechanism to hijack methods. Here is an implementation in pure C# code that you can use in the meantime:

    [DllImport ("/usr/lib/libobjc.dylib")]
extern static IntPtr class_getInstanceMethod (IntPtr classHandle, IntPtr Selector);
[DllImport ("/usr/lib/libobjc.dylib")]
extern static Func<IntPtr,IntPtr,IntPtr> method_getImplementation (IntPtr method);
[DllImport ("/usr/lib/libobjc.dylib")]
extern static IntPtr imp_implementationWithBlock (ref BlockLiteral block);
[DllImport ("/usr/lib/libobjc.dylib")]
extern static void method_setImplementation (IntPtr method, IntPtr imp);

static Func<IntPtr,IntPtr,IntPtr> original_impl;

void HijackWillMoveToSuperView ()
{
var method = class_getInstanceMethod (new UIView ().ClassHandle, new Selector ("willMoveToSuperview:").Handle);
original_impl = method_getImplementation (method);
var block_value = new BlockLiteral ();
CaptureDelegate d = MyCapture;
block_value.SetupBlock (d, null);
var imp = imp_implementationWithBlock (ref block_value);
method_setImplementation (method, imp);
}

delegate void CaptureDelegate (IntPtr block, IntPtr self, IntPtr uiView);

[MonoPInvokeCallback (typeof (CaptureDelegate))]
static void MyCapture (IntPtr block, IntPtr self, IntPtr uiView)
{
Console.WriteLine ("Moving to: {0}", Runtime.GetNSObject (uiView));
original_impl (self, uiView);
Console.WriteLine ("Added");
}

How to Invoke the IntPtr result of method_getImplementation

You need to use Marshal.GetDelegateForFunctionPointer and add [MonoNativeFunctionWrapper] to the delegate type:

[MonoNativeFunctionWrapper]
public delegate void ViewWillAppearDelegate (IntPtr self, IntPtr selector);

var del = (ViewWillAppearDelegate) Marshal.GetDelegateForFunctionPointer (original_impl, typeof (ViewWillAppearDelegate));
del (obj.Handle, Selector.GetHandle ("viewWillAppear"));

Calling method_getImplementation throws ExecutionEngineException on device

The return value is an "IntPtr", not a "Func".

How to add subview above the keyboard in monotouch/Xamarin.Ios?

This Worked for me.

UIApplication.SharedApplication.Windows[1].AddSubview(myView);

Without subclassing a UIView or UIViewController: possible to catch if a subview was added?

Not that I think this method is cleaner than the one @tiguero suggested, but I think it's slightly safer (see why using categories could be dangerous in my comments to his answer) and offers you more flexibilty.

This is somehow, although not exactly, but more at the conceptual level, the same way KVO works. You basically, dynamically alter the implementation of willMoveToSuperview and add your notification code to it.

//Makes views announce their change of superviews
Method method = class_getInstanceMethod([UIView class], @selector(willMoveToSuperview:));
IMP originalImp = method_getImplementation(method);

void (^block)(id, UIView*) = ^(id _self, UIView* superview) {
[_self willChangeValueForKey:@"superview"];
originalImp(_self, @selector(willMoveToSuperview:), superview);
[_self didChangeValueForKey:@"superview"];
};

IMP newImp = imp_implementationWithBlock((__bridge void*)block);
method_setImplementation(method, newImp);

MonoTouch: UIApplicationDelegate - is OnActivated needed?

If your app will run on iOS 3, yes it is still needed. Otherwise, you only need it to capture when your app transitions to the active state (eg. when the multitasking bar is displayed and you get back to your app when you tap on it).



Related Topics



Leave a reply



Submit