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?
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.
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. 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.
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, e.g.
_HandleSaveButtonTouchUpInside (url, data);
If you need to dispatch via Obj-C for some reason, but don't need the delay, use MonoTouch.ObjCRuntime.Messaging, e.g.
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. MonoTouch has added special support for this to use an NSAction delegate, so you can use a C# lambda to capture arguments safely.
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. Maybe one of the Xamarin Engineers can confirm this.
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);
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With