简体   繁体   English

如何使用MonoTouch.ObjCRuntime.Selector和Perform Selector发送参数

[英]How do I send parameters using MonoTouch.ObjCRuntime.Selector and Perform Selector

Here is an example I found, but they omitted actually sending the params. 这是我发现的一个例子,但它们实际上省略了发送参数。

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

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

I would like to be able to do something like this: 我希望能够做到这样的事情:

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

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

How do I change the PerformSelector Call to send params to the method? 如何更改PerformSelector Call以将params发送到方法?

The MonoTouch docs indicate that method maps to the Obj-C selector performSelector:withObject:afterDelay , which only supports invoking a selector with a single argument. MonoTouch文档指示方法映射到Obj-C选择器performSelector:withObject:afterDelay ,它仅支持使用单个参数调用选择器。

The best way to handle this depends what you need to do. 处理此问题的最佳方法取决于您需要做什么。 One typical way to handle this would be to put the arguments as properties/fields on a single NSObject, then the target would be modified to have a single argument, and pull the real arguments off that method. 处理此问题的一种典型方法是将参数作为属性/字段放在单个NSObject上,然后将目标修改为具有单个参数,并从该方法中提取实际参数。 If you did this with a custom MonoTouch object, you'd have to watch out for the GC collecting the managed peer, if nothing in managed code kept a reference to it. 如果您使用自定义MonoTouch对象执行此操作,则必须注意收集托管对等方的GC,如果托管代码中没有任何内容保留对它的引用。

A better solution would depend on exactly how you're using it. 更好的解决方案取决于您使用它的确切方式。 For example, in your example, you could trivially call the C# method directly, eg 例如,在您的示例中,您可以直接调用C#方法,例如

_HandleSaveButtonTouchUpInside (url, data);

If you need to dispatch via Obj-C for some reason, but don't need the delay, use MonoTouch.ObjCRuntime.Messaging , eg 如果由于某种原因需要通过Obj-C发送,但不需要延迟,请使用MonoTouch.ObjCRuntime.Messaging ,例如

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

If you need the delay, you could use an NSTimer . 如果您需要延迟,可以使用NSTimer MonoTouch has added special support for this to use an NSAction delegate, so you can use a C# lambda to capture arguments safely. MonoTouch为此添加了特殊支持以使用NSAction委托,因此您可以使用C#lambda安全地捕获参数。

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

I could not find the binding for this call either. 我也找不到这个电话的绑定。 In the sample below I added my own overload for PerformSelector. 在下面的示例中,我为PerformSelector添加了自己的重载。 Maybe one of the Xamarin Engineers can confirm this. 也许其中一位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);
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM