2012-05-07 3 views
7

여기에 예제가 있지만 실제로 매개 변수를 보내는 것은 생략되었습니다.MonoTouch.ObjCRuntime.Selector 및 Perform 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

는 단일 인자와 호출 선택을 지원하여 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# 람다를 사용하여 인수를 안전하게 캡처 할 수 있습니다.

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

철저한 답변을 해주셔서 감사합니다. 코코아가 화면을 다시 그리기 위해 메인 스레드를 비울 필요가있을 때 PerformSelector를 사용했습니다. 그런 다음 일부 논리 처리로 돌아갈 수있었습니다. 지금은 내가 가지고있는 루프에 대한 writeStream 중에 화면에 그려진 진행 막대의 해당 항목을 업데이트하려고합니다. for 루프 내에 perform selector를 놓고 진행 막대의 속성을 업데이트하여 화면을 본질적으로 새로 고칠 수 있는지 확인하고 싶습니다. –

+0

또 다른 방법은 논리/스트림에 스레드를 사용하고 스레드에서 InvokeOnMainThread를 사용하여 UI를 업데이트하는 것입니다. –

+0

원본 개발자가 특정 속성을 바인딩하지 않았거나 소스를 릴리스하지 않았기 때문에 수동으로 라이브러리를 리 바인드하지 않아도되었습니다. 감사합니다. 관심있는 사람은 setColor를 호출하여 msgSend_IntPtr_IntPtr 메서드를 사용하여 속성을 쉽게 설정할 수 있습니다. 여기서 color는 속성의 이름입니다. (Arg 0은 속성 값입니다. Arg 1 = IntPtr.Zero) – Dermot

4

이 호출에 대한 바인딩을 찾을 수 없습니다. 아래 샘플에서는 PerformSelector에 대한 자체 오버로드를 추가했습니다. 아마도 Xamarin 엔지니어 중 한 명이이 사실을 확인할 수 있습니다. MonoTouch docs

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

모노 터치 선택기의 굉장한 과부하! 내 프로젝트 홈즈에서 이것을 시도해 볼 수 있습니다. 공유해 주셔서 감사합니다. PerformSelector를 찾는 사람들이이 질문에 빠지기를 바랍니다. –

관련 문제