2017-04-25 1 views
0

바인딩 프로젝트를 가져 오려고합니다. 하지만 다른 대리자에 매개 변수로 대리자를 전달하는 것이 좋지 않은 오류가 발생했습니다.바인딩 프로젝트에서 다른 대리인의 매개 변수로 대리인을 전달할 수 있습니까?

내가받는 오류는 다음과 같습니다.

"Attempting to JIT compile method '(wrapper runtime-invoke) 
:BackgroundFetchResultHandler(object,UIBackgroundFetchResult)' while running 
with --aot-only. 

그래서 무슨 일이 일어나고 있는지입니다 내가 PushySDK를 사용하고 바인딩 프로젝트. 모두가 BackgroundFetchResultHandler 대리인을 제외하고 작동하는 바인딩 라이브러리 프로젝트를 만든거야 "

합니다. 자세한 내용은 http://docs.xamarin.com/ios/about/limitations를 참조합니다. \ n 나는 경우 바인딩 늘 컴파일 LIB 대신 BackgroundFetchResultHandler에 대한 대리인의 행동이나 Func을 사용하려고

내 apiDefinitions.cs 파일이입니다.

using System; 
using Foundation; 
using UIKit; 

namespace PushySDK 
{ 
    public delegate void BackgroundFetchResultHandler(UIBackgroundFetchResult result); 
    public delegate void NotificationHandler(NSDictionary info, BackgroundFetchResultHandler action); 

    // @interface Pushy : NSObject 
    [BaseType(typeof(NSObject), Name = "_TtC8PushySDK5Pushy")] 
    [DisableDefaultCtor] 
    interface Pushy 
    { 
     // -(instancetype _Nonnull)init:(UIResponder * _Nonnull)appDelegate application:(UIApplication * _Nonnull)application __attribute__((objc_designated_initializer)); 
     [Export("init:application:")] 
     [DesignatedInitializer] 
     IntPtr Constructor(UIResponder appDelegate, UIApplication application); 

     // -(void)setNotificationHandler:(void (^ _Nonnull)(NSDictionary * _Nonnull, void (^ _Nonnull)(UIBackgroundFetchResult)))notificationHandler; 
     [Export("setNotificationHandler:")] 
     void SetNotificationHandler(NotificationHandler notificationHandler); 

     // -(void)register:(void (^ _Nonnull)(NSError * _Nullable, NSString * _Nonnull))registrationHandler; 
     [Export("register:")] 
     void Register(Action<NSError, NSString> registrationHandler); 
    } 
} 

위임 대신 작업을 사용하려고했지만 동일한 오류가 발생합니다. NotificationHandler Delegate를 다음과 같이 변경하면;

public delegate void NotificationHandler(NSDictionary info, int action); 

Everythign은 정수이기 때문에 콜백을 호출 할 수 없다는 점을 제외하고는 정상적으로 작동합니다. 하지만 푸시 알림이 제대로 작동하고 모두 정상입니다.

그래서이 콜백을 충돌하지 않고 호출하는 방법을 찾으려고합니다. Xamarin이 바인딩 코드를 생성 할 때 두 번째 대리자의 유형을 결정하는 데 많은 어려움이있는 것 같습니다.

이렇게 NotificatioNHandler를 사용하면;

public delegate void NotificationHandler(NSDictionary info, Action<UIBackgroundFetchResult> action); 

바인딩 라이브러리 늘 컴파일하고 내가 잘못된 문자 "Action`1"에 대해 오류가

는 사람이 작업을 얻을 생각할 수 어쨌든입니다. 미리 감사드립니다!

답변

0

좋아, 그래서 그들은 첫 번째 대리인을 어떻게 수행했는지 알아보기 위해 obj 폴더의 컴파일 된 코드를 살펴 보았습니다. 그래서 그냥 델리게이트 형식으로 복사하여 IntPtr로 변경했습니다. 내 API 정의 파일이 이런 식으로 끝났다.

using System; 
using Foundation; 
using UIKit; 
using ObjCRuntime; 

namespace PushySDK 
{ 
internal delegate void NotificationHandler(NSDictionary info, IntPtr action); 

// @interface Pushy : NSObject 
[BaseType(typeof(NSObject), Name = "_TtC8PushySDK5Pushy")] 
[DisableDefaultCtor] 
interface Pushy 
{ 
    // -(instancetype _Nonnull)init:(UIResponder * _Nonnull)appDelegate application:(UIApplication * _Nonnull)application __attribute__((objc_designated_initializer)); 
    [Export("init:application:")] 
    [DesignatedInitializer] 
    IntPtr Constructor(UIResponder appDelegate, UIApplication application); 

    // -(void)setNotificationHandler:(void (^ _Nonnull)(NSDictionary * _Nonnull, void (^ _Nonnull)(UIBackgroundFetchResult)))notificationHandler; 
    [Export("setNotificationHandler:")] 
    void SetNotificationHandler(NotificationHandler notificationHandler); 

    // -(void)register:(void (^ _Nonnull)(NSError * _Nullable, NSString * _Nonnull))registrationHandler; 
    [Export("register:")] 
    void Register(Action<NSError, NSString> registrationHandler); 
} 
} 

콜백이 할당 될 내 APPDelegate 클래스에서 대리인을 선언합니다.

[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] 
internal delegate void DBackgroundFetchResultHandler(IntPtr blockPtr, nuint result); 

선언이 내부 AppDelegate에 내부 클래스뿐만 아니라 다음

internal class BackgroundFetchResultHandlerProxy 
    { 
     IntPtr blockPtr; 
     DBackgroundFetchResultHandler invoker; 

     [Preserve(Conditional = true)] 
     public unsafe BackgroundFetchResultHandlerProxy(BlockLiteral* block) 
     { 
      blockPtr = _Block_copy((IntPtr)block); 
      invoker = block->GetDelegateForBlock<DBackgroundFetchResultHandler>(); 
     } 

     [Preserve(Conditional = true)] 
     ~BackgroundFetchResultHandlerProxy() 
     { 
      _Block_release(blockPtr); 
     } 

     [Preserve(Conditional = true)] 
     internal unsafe void Invoke(UIBackgroundFetchResult result) 
     { 
      invoker(blockPtr, (nuint) (UInt64) result); 
     } 
    } 

와 나는 임 수

pushy.SetNotificationHandler(HandleNotification); 
를 호출 한 후

[Export("handleNotification:completionHandler:")] 
internal unsafe void HandleNotification(NSDictionary info, IntPtr actionPtr) 
{ 
    var proxy = new BackgroundFetchResultHandlerProxy((BlockLiteral *)actionPtr); 
     proxy.Invoke(UIBackgroundFetchResult.NewData); 
} 

및 내 기능 변경

관련 문제