2012-05-07 7 views
7

ここに示した例がありますが、実際にはパラメータを送信することは省略されています。MonoTouch.ObjCRuntime.SelectorとPerform Selectorを使用してパラメータを送信する方法

this.PerformSelector(new MonoTouch.ObjCRuntime.Selector("_HandleSaveButtonTouchUpInside"),null,0.0f); 

[Export("_HandleSaveButtonTouchUpInside")] 
    void _HandleSaveButtonTouchUpInside() 
    { 
... 
} 

私はこのような何かをできるようにしたいと思います:

this.PerformSelector(new MonoTouch.ObjCRuntime.Selector("_HandleSaveButtonTouchUpInside"),null,0.0f); 

[Export("_HandleSaveButtonTouchUpInside")] 
    void _HandleSaveButtonTouchUpInside(NSURL url, NSData data) 
    { 
... 
} 

私は方法にのparamsを送信するためにPerformSelectorコールを変更するにはどうすればよいですか?

答えて

9

MonoTouch docsメソッドが単一の引数でセレクタを起動サポートのObj-CセレクタperformSelector:withObject:afterDelay、にマッピングすることを示します。

これを処理する最善の方法は、必要な作業によって異なります。これを処理する一般的な方法の1つは、引数をプロパティ/フィールドとして単一のNSObjectに配置し、ターゲットを単一の引数に変更し、その引数から実際の引数を取り除くことです。カスタムMonoTouchオブジェクトでこれを行った場合、マネージコード内の何も参照を保持していなければ、マネージドピアを収集するGCを気にする必要があります。

よりよい解決方法は、使用方法によります。たとえば、あなたの例では、簡単にC#メソッドを直接呼び出すことができます(例:

_HandleSaveButtonTouchUpInside (url, data); 

あなたは、例えば、何らかの理由でのObj-Cを経由して派遣するが、遅延を必要としない、MonoTouch.ObjCRuntime.Messagingを使用する必要がある場合あなたが遅延を必要とする場合

MonoTouch.ObjCRuntime.Messaging.void_objc_msgSend_IntPtr_IntPtr (
    target.Handle, 
    MonoTouch.ObjCRuntime.Selector.GetHandle ("_HandleSaveButtonTouchUpInside"), 
    arg0.Handle, 
    arg1.Handle); 

は、あなたがNSTimerを使用することができます。 MonoTouchはNSActionデリゲートを使用するために特別なサポートを追加しました。したがって、C#ラムダを使用して引数を安全に取得できます。

NSTimer.CreateScheduledTimer (someTimespan,() => _HandleSaveButtonTouchUpInside (url, data)); 
+0

徹底的な回答をいただきありがとうございます。私は、ココアが画面を再描画するようにメインスレッドを解放する必要があるときにPerformSelectorを使用していました。その後、いくつかのロジックの処理に戻ることができました。今私は、私が持っているループのためのwriteStream中に画面に描画されたプログレスバーの同等のものを更新しようとしています。 forループ内にperformセレクタを置き、プログレスバーのプロパティを更新して、画面を本質的にリフレッシュできるかどうかを確認したい。 –

+0

これを行うもう1つの方法は、ロジック/ストリーム用のスレッドを使用し、スレッドからInvokeOnMainThreadを使用してUIを更新することです。 –

+0

これは、元の開発者が特定のプロパティをバインドしなかったか、ソースを解放しなかったため、手動でライブラリを再バインドする必要がなくなりました。ありがとうございます。関心のある人は、setColorを呼び出してmsgSend_IntPtr_IntPtrメソッドを使ってプロパティを簡単に設定できます。ここで、colorはプロパティの名前です。 (Arg 0はプロパティ値です、Arg 1 = IntPtr.Zero) – Dermot

4

この呼び出しのバインディングも見つかりませんでした。以下のサンプルでは、​​PerformSelectorのための独自のオーバーロードを追加しました。たぶん、Xamarinのエンジニアの一人がこれを確認できます。

using System; 
using MonoTouch.Foundation; 
using MonoTouch.UIKit; 
using MonoTouch.ObjCRuntime; 
using System.Runtime.InteropServices; 

namespace delete20120506 
{ 
    [Register ("AppDelegate")] 
    public partial class AppDelegate : UIApplicationDelegate 
    { 
     UIWindow window; 

     public override bool FinishedLaunching (UIApplication app, NSDictionary options) 
     { 
      window = new UIWindow (UIScreen.MainScreen.Bounds); 

      // 
      Target target = new Target(); 
      NSUrl url = new NSUrl ("http://xamarin.com/"); 
      NSData nsData = NSData.FromString ("Hello"); 

      target.PerformSelector (new MonoTouch.ObjCRuntime.Selector 
            ("TestSelUrl:withData:"), url, nsData); 

      window.MakeKeyAndVisible(); 

      return true; 
     } 
    } 

    [Register ("Target")] 
    public class Target : NSObject 
    { 
     public Target() : base (NSObjectFlag.Empty) {} 

     [Export("TestSelUrl:withData:")] 
     void TestSelUrlWithData(NSUrl url, NSData nsData) 
     { 
      Console.WriteLine ("In TestSelUrlWithData"); 
      Console.WriteLine (url.ToString()); 
      Console.WriteLine (nsData.ToString()); 
      return; 
     } 

     [DllImport ("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] 
     public static extern void void_objc_msgSend_intptr_intptr_intptr (IntPtr receiver, IntPtr selector, IntPtr arg1, IntPtr arg2, IntPtr arg3); 

     [DllImport ("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSendSuper")] 
     public static extern void void_objc_msgSendSuper_intptr_intptr_intptr (IntPtr receiver, IntPtr selector, IntPtr arg1, IntPtr arg2, IntPtr arg3); 


     public virtual void PerformSelector (MonoTouch.ObjCRuntime.Selector sel, 
               NSObject arg1, NSObject arg2) 
     { 
      if (this.IsDirectBinding) 
      { 
       void_objc_msgSend_intptr_intptr_intptr (this.Handle, 
        Selector.GetHandle ("performSelector:withObject:withObject:"), 
        sel.Handle, arg1.Handle, arg2.Handle); 
      } 
      else 
      { 
       void_objc_msgSendSuper_intptr_intptr_intptr (this.SuperHandle, 
        Selector.GetHandle ("performSelector:withObject:withObject:"), sel.Handle, 
        arg1.Handle, arg2.Handle); 
      } 
     } 
    } 
} 
+0

モノトゥッチセレクタの素晴らしいオーバーロード!私は私のプロジェクトのホームズでこれを試してみるかもしれません。共有していただきありがとうございます。私はPerformSelectorを探している人たちがこの質問になることを願っています。 –