如何使用 MonoTouch.ObjCRuntime.Selector 和 Execute Selector 发送参数
本文关键字:Selector 参数 Execute MonoTouch ObjCRuntime 何使用 | 更新日期: 2023-09-27 18:33:18
这是我找到的一个例子,但他们省略了实际发送参数。
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)
{
...
}
如何更改执行选择器调用以将参数发送到该方法?
MonoTouch 文档指出该方法映射到 Obj-C 选择器 performSelector:withObject:afterDelay
,它仅支持使用单个参数调用选择器。
处理此问题的最佳方法取决于您需要做什么。处理此问题的一种典型方法是将参数作为属性/字段放在单个 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# lambda 安全地捕获参数。
NSTimer.CreateScheduledTimer (someTimespan, () => _HandleSaveButtonTouchUpInside (url, data));
我也找不到此调用的绑定。 在下面的示例中,我为 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);
}
}
}
}