2013-01-02 15 views
5

私の質問からここに:Without subclassing a UIView or UIViewController: possible to catch if a subview was added?MonoTouchに "method_getImplementation"と "method_setImplementation"を移植する方法は?

私はMonoTouchの答えからコードを移植する方法を知っています。基本的には、メソッドを新しいものに置き換え、サブクラス化せずに古いメソッドを呼び出します。このポインタをMonoTouchで動作させるようにすることは、まったく可能ですか?

+0

私はそれがどのように実行できるのか興味があります。今は、ObjCライブラリとリンクしています。 –

答えて

6

これは、方法を乗っ取りするための汎用メカニズムを提供するための良い候補のようです。

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

あなたはそれがApp Storeの保存だと思いますか? – Krumelur

+0

ハイジャックされたメソッドをリセットして元のメソッドを再度使用するにはどうすればよいですか? – Krumelur

+0

@Krumelur:元のメソッドに戻るには、 'method_setImplementation(method、original_impl);'を呼び出すだけです。 –

0

私はそれがデバイスに取り組んで取得するにはミゲルの例を次のように変更しなければならなかった。ここでは、その間に使用できる純粋なC#コードでの実装があります。

 [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"); 
     } 
関連する問題