2012-05-07 17 views
7

以下是我找到的一個示例,但它們實際上省略了發送參數。如何使用MonoTouch.ObjCRuntime.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) 
    { 
... 
} 

如何改變PerformSelector調用發送PARAMS的方法?

回答

9

MonoTouch docs指示方法映射到對象 - 選擇器performSelector:withObject:afterDelay,只支持帶一個參數調用的選擇器。

處理此問題的最佳方法取決於您需要做的事情。處理這種情況的一種典型方法是將參數作爲屬性/字段放在單個NSObject上,然後將目標修改爲具有單個參數,並將該實參從該方法中提取出來。如果您使用自定義的MonoTouch對象執行此操作,則必須注意GC收集託管對等項,如果託管代碼中沒有任何內容保留對其的引用。

更好的解決方案將取決於你如何使用它。例如,在您的示例中,您可以直接調用C#方法,例如

_HandleSaveButtonTouchUpInside (url, data); 

如果需要通過對象 - 派遣出於某種原因,但不需要延遲,使用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#lambda安全地捕獲參數。

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

謝謝你的徹底答案mhutch。當我需要釋放主線程以使可可重新繪製屏幕時,我一直在使用PerformSelector,然後我可以重新處理一些邏輯。現在我正試圖更新一個進度條的等價物,這個進度條在writeStream for循環中已經繪製到屏幕上。想要看看我是否可以通過在for循環中添加一個執行選擇器並更新進度條的屬性來刷新屏幕。 –

+0

另一種方法是使用邏輯/流的線程,並使用線程中的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

MonoTouch Selector真棒超載!我可以在我的福爾摩斯項目中嘗試這個。感謝你的分享。我希望那些正在尋找PerformSelector的人會遇到這個問題。 –

相關問題