如何将“method_getImplementation”和“method_setImplementation”移植到MonoTouch?

从我的问题在这里: 没有子类UIView或UIViewController:可能赶上如果子视图被添加?

我想知道如何将代码从答案移植到MonoTouch。 它基本上用一个新的方法replace一个方法,然后调用旧的没有子类化。 是否有可能得到这个指针杂耍它在MonoTouch中工作?

//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); 

这看起来是我们提供通用机制来劫持方法的一个很好的select。 以下是您可以在此期间使用的纯C#代码的实现:

  [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"); } 

我不得不对Miguel的例子进行如下修改,以使其在设备上运行。

  [DllImport("/usr/lib/libobjc.dylib")] extern static IntPtr class_getInstanceMethod(IntPtr classHandle, IntPtr Selector); [DllImport("/usr/lib/libobjc.dylib")] extern static 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 IntPtr original_impl; [MonoNativeFunctionWrapper] public delegate void OriginalDelegate(IntPtr one,IntPtr two); static 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)); var del = (OriginalDelegate) Marshal.GetDelegateForFunctionPointer (original_impl,typeof(OriginalDelegate)); del (self, uiView); Console.WriteLine("Added"); }