Трудность связывания метода делегата iOS без параметров

2

При привязке iOS lib.a для Xamarin у меня появляется следующая ошибка:

btouch: The delegate method Device.SomeDeviceDelegate.CaptureComplete needs to take at least one parameter (BI1003)

Были созданы привязки Objective Sharpie.

namespace Device 
{   

    // @protocol SomeDeviceDelegate <NSObject>
    [Protocol, Model, Preserve]
    [BaseType(typeof(NSObject))]
    interface SomeDeviceDelegate
    {
        // @optional -(void)CaptureComplete;
        [Export("CaptureComplete")]
        void CaptureComplete();
    }

    // @interface SomeDevice : NSObject
    [Protocol, Model, Preserve]
    [BaseType(typeof(NSObject), Delegates = new[] { "WeakDelegate" }, Events = new[] { typeof(SomeDeviceDelegate) })]
    interface SomeDevice
    {
        [Wrap("WeakDelegate")]
        SomeDeviceDelegate Delegate { get; set; }

        // @property (assign, nonatomic) id<SomeDeviceDelegate> delegate;
        [NullAllowed, Export("delegate", ArgumentSemantic.Assign)]
        SomeDeviceDelegate WeakDelegate { get; set; }
    }

}

NB. Я сменил имя на SomeDevice чтобы скрыть имя устройства/устройства (NDA).

Компилятор жалуется, что //@optional -(void)CaptureComplete; и соответствующее связывание CaptureComplete() не имеет параметров и что ему требуется хотя бы один.

В: Что мне нужно сделать, чтобы связать этот делегат?

Я попробовал Справочное руководство по типам привязок и попытался применить

  • Атрибут EventArgs
  • NoDefaultValue
  • DefaultValueFromArgument

ОБНОВИТЬ

Я неправильно понял NoDefaultValue и DefaultValueFromArgument, они используются, когда делегат возвращает значение (например, bool), поскольку возврат мешает обертыванию события Xamarin.

Теги:
xamarin
xamarin.ios

2 ответа

2
Лучший ответ

Я нашел решение поздно вечером и закрыл этот вопрос для тех, кто сталкивается с тем же сообщением об ошибке.

NB: На этот раз не изменились имена, так как они сделали ответ менее ясным.

Предпочтительный способ обработки делегата ObjC состоит в том, чтобы разоблачить их как События, например

// @interface ICBarCodeReader : ICISMPDevice
[DisableDefaultCtor]
[BaseType(typeof(ICISMPDevice), Delegates = new[] { "WeakDelegate" }, Events = new[] { typeof(ICBarCodeReaderDelegate) }))]
public interface ICBarCodeReader
{
    [Wrap("WeakDelegate")]
    ICBarCodeReaderDelegate Delegate { get; set; }

    // @property (assign, nonatomic) id<ICISMPDeviceDelegate,ICBarCodeReaderDelegate> delegate;
    [NullAllowed, Export("delegate", ArgumentSemantic.Assign)]
    ICBarCodeReaderDelegate WeakDelegate { get; set; }
}

Параметр Delegate и Events BaseType генерирует коды, которые обертывают каждый метод в ICBarCodeReaderDelegate.

// @protocol ICBarCodeReaderDelegate
[Protocol, Model, Preserve]
[BaseType(typeof(ICISMPDeviceDelegate))]
public interface ICBarCodeReaderDelegate
{
    // @required -(void)barcodeData:(id)data ofType:(int)type;
    [Abstract]
    [Export("barcodeData:ofType:")]
    [EventArgs("BarcodeData")]
    void BarcodeData(string data, BarCodeSymbologies type);

    // @required -(void)configurationRequest;
    [Abstract]
    [Export("configurationRequest")]
    void ConfigurationRequest();
}

Это позволяет вам в вашем проекте:

public void Init()
{
    _sharedBarCodeReader.BarcodeData += OnBarcodeData;
}

private void OnBarcodeData(object sender, BarcodeDataEventArgs e)
{
    var barcode = Convert.ToString(sender); // this maps to string data
    //BarCodeSymbologies is in BarcodeDataEventArgs

    var handler = BarCodeData;
    if (handler != null)
        handler(this, barcode);
}

Однако этот подход терпит неудачу, когда метод не имеет параметров, как сказано в сообщении об ошибке btouch.

Другой подход, который я только обнаружил (и теперь кажется прямым и простым), заключается не в том, чтобы делегировать делегата как события, например

// @interface ICBarCodeReader : ICISMPDevice
[DisableDefaultCtor]
[BaseType(typeof(ICISMPDevice))]
public interface ICBarCodeReader
{
    [Wrap("WeakDelegate")]
    ICBarCodeReaderDelegate Delegate { get; set; }

    // @property (assign, nonatomic) id<ICISMPDeviceDelegate,ICBarCodeReaderDelegate> delegate;
    [NullAllowed, Export("delegate", ArgumentSemantic.Assign)]
    ICBarCodeReaderDelegate WeakDelegate { get; set; }
}

И вместо этого создайте реализацию интерфейса делегата.

например

public void Init()
{
    _sharedBarCodeReader.Delegate = new BarCodeReaderDelegate(this);
}

private class BarCodeReaderDelegate : ICBarCodeReaderDelegate
{
    public BarCodeReaderDelegate(BarCodeScanner barCodeScanner)
    {
        _barCodeScanner = barCodeScanner;
    }

    public override void BarcodeData(string data, BarCodeSymbologies type)
    {
        var handler = _barCodeScanner.BarCodeData;
        if (handler != null)
            handler(this, data);
    }

    public override void ConfigurationRequest() { }

    private readonly BarCodeScanner _barCodeScanner;
}

Надеюсь, это поможет кому-то другому.

0

"CaptureComplete:" Может ли ожидать отправителя?

  • 0
    Я так и думал, однако подпись ObjC не предполагает, что это так. Я попытался добавить параметр в управляемый метод, однако при этом другой registrar found a signature mismatch in the method ошибке registrar found a signature mismatch in the method дальнейшем.
  • 0
    Я добавил : в [Export()] и теперь он компилируется.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню