2013-01-02 3 views
5

Von meiner Frage hier: Without subclassing a UIView or UIViewController: possible to catch if a subview was added?Wie portiere ich "method_getImplementation" und "method_setImplementation" an MonoTouch?

Ich frage mich, wie man den Code von der Antwort auf MonoTouch portieren. Es ersetzt im Grunde eine Methode durch eine neue und ruft dann die alte ohne Unterklassen auf. Ist es überhaupt möglich, diesen Zeiger zu jonglieren, damit er in MonoTouch funktioniert?

+0

Ich bin auch neugierig, wie es gemacht werden könnte. Im Moment verlinke ich nur mit einer ObjC-Bibliothek, die das tut. –

Antwort

6

Dies sieht aus wie ein guter Kandidat für uns, um einen allgemeinen Mechanismus bereitzustellen, um Methoden zu entführen. Hier ist eine Implementierung in reinen C# Code, den Sie in der Zwischenzeit verwenden können:

[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

Glaubst du, es ist App Store speichern? – Krumelur

+0

Wie setze ich die entführte Methode zurück und verwende sie erneut? – Krumelur

+0

@Krumelur: Rufen Sie 'method_setImplementation (method, original_impl);' auf, um zum ursprünglichen zurückzukehren. –

0

Ich hatte die folgenden Änderungen an Miguel Beispiel zu machen, um es auf einem Gerät zu erhalten zu arbeiten.