2012-05-07 24 views
7

Đây là ví dụ tôi tìm thấy, nhưng chúng bỏ qua thực sự gửi các thông số.Làm cách nào để gửi thông số bằng MonoTouch.ObjCRuntime.Selector và Thực hiện chọn

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

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

Tôi muốn để có thể làm điều gì đó như thế này:

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

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

Làm thế nào để thay đổi performSelector Gọi để gửi params để phương pháp này?

Trả lời

9

Các MonoTouch docs chỉ ra rằng bản đồ phương pháp để chọn obj-C performSelector:withObject:afterDelay, mà chỉ hỗ trợ cách gọi một selector với một đối số duy nhất.

Cách tốt nhất để xử lý việc này phụ thuộc vào những gì bạn cần làm. Một cách điển hình để xử lý điều này là đặt các đối số là các thuộc tính/trường vào một NSObject đơn lẻ, sau đó đích sẽ được sửa đổi để có một đối số duy nhất và kéo các đối số thực ra khỏi phương thức đó. Nếu bạn đã làm điều này với một đối tượng MonoTouch tùy chỉnh, bạn sẽ phải xem ra cho GC thu thập các peer được quản lý, nếu không có gì trong quản lý mã giữ một tham chiếu đến nó.

Giải pháp tốt hơn sẽ phụ thuộc vào chính xác cách bạn đang sử dụng. Ví dụ: trong ví dụ của bạn, bạn có thể trực tiếp gọi phương thức C#, ví dụ:

_HandleSaveButtonTouchUpInside (url, data); 

Nếu bạn cần phải gửi qua obj-C đối với một số lý do, nhưng không cần sự chậm trễ, sử dụng MonoTouch.ObjCRuntime.Messaging, ví dụ

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

Nếu bạn cần sự chậm trễ, bạn có thể sử dụng NSTimer. MonoTouch đã thêm hỗ trợ đặc biệt cho việc này để sử dụng một đại biểu NSAction, vì vậy bạn có thể sử dụng C# lambda để nắm bắt các đối số một cách an toàn.

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

Cảm ơn bạn đã trả lời kỹ lưỡng mhutch. Tôi đã sử dụng PerformSelector khi tôi cần giải phóng chủ đề chính sao cho ca cao sẽ vẽ lại màn hình, và sau đó tôi có thể quay lại xử lý một số logic. Ngay bây giờ tôi đang cố gắng để cập nhật tương đương với một thanh tiến trình đã được rút ra màn hình trong một writeStream cho vòng lặp mà tôi có. Muốn xem nếu tôi về cơ bản có thể làm mới màn hình bằng cách đặt một bộ chọn thực hiện trong vòng lặp và cập nhật thuộc tính của thanh tiến trình. –

+0

Một cách khác để thực hiện điều đó là sử dụng luồng cho luồng/luồng và sử dụng InvokeOnMainThread từ chuỗi để cập nhật giao diện người dùng. –

+0

Điều này đã giúp tôi không phải tự rebind một thư viện vì nhà phát triển ban đầu không ràng buộc một thuộc tính cụ thể hoặc phát hành nguồn, vì vậy cảm ơn bạn. Đối với bất kỳ ai quan tâm, các thuộc tính có thể dễ dàng được thiết lập bằng cách sử dụng phương thức msgSend_IntPtr_IntPtr bằng cách gọi setColor: nơi màu là tên của thuộc tính. (Arg 0 là giá trị tài sản, Arg 1 = IntPtr.Zero) – Dermot

4

Tôi không thể tìm thấy ràng buộc cho cuộc gọi này. Trong ví dụ bên dưới, tôi đã thêm quá tải của riêng mình cho PerformSelector. Có lẽ một trong những kỹ sư Xamarin có thể xác nhận điều này.

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

Quá tải tuyệt vời bộ chọn Monotouch! Tôi có thể thử cái này trong holmes dự án của tôi. Cảm ơn bạn đã chia sẻ. Tôi hy vọng rằng những người đang tìm PerformSelector sẽ rơi vào câu hỏi này. –

Các vấn đề liên quan