c# - 难以绑定(bind)不带参数的 iOS 委托(delegate)方法

标签 c# ios objective-c xamarin xamarin.ios

为 Xamarin 绑定(bind) iOS lib.a 时,出现以下错误:

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

绑定(bind)已生成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; }
    }

}

注意。我已将名称更改为 SomeDevice 以隐藏硬件/设备名称 (NDA)。

编译器提示 //@optional -(void)CaptureComplete; 和相应的绑定(bind) CaptureComplete() 没有参数,并且它至少需要一个参数。

问:我需要做什么才能绑定(bind)此委托(delegate)?

我已经尝试过Binding Types Reference Guide并尝试应用

  • EventArgs 属性
  • NoDefaultValue 属性
  • DefaultValueFromArgument 属性

更新

我误解了 NoDefaultValueDefaultValueFromArgument 属性,它们在委托(delegate)返回值(例如 bool)时使用,因为返回会干扰事件的 Xamarin 包装。

最佳答案

我找到了解决方案。

注意:这次我没有更改名称,因为这使得答案不太清楚。

处理 ObjC 委托(delegate)的首选方法是将它们公开为事件,例如

// @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; }
}

BaseType 的 Delegate 和 Events 参数生成包装 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 错误消息所示。

我刚刚发现的另一种方法(现在看起来直接且简单)是不将委托(delegate)包装为事件,例如

// @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; }
}

而是创建 Delegate 接口(interface)的实现。

例如

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;
}

关于c# - 难以绑定(bind)不带参数的 iOS 委托(delegate)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29909810/

相关文章:

javascript - 解析[错误] : success/error was not called (Code: 141, 版本 : 1. 9.0)

c# - 根据另一个 DataGridView 的行过滤 BindingSource

ios - 安装AFNetworking 2.0后编译报错

ios - 无法在 <Text/> 中创建 <ActivityIndi​​catorIOS/>

objective-c - 相同的代码在一个项目中产生错误,但不会在另一个项目中产生错误

objective-c - Finder 使用哪个 NSView 来显示文件?

ios - UIButton 没有正确定位自己并且没有出现在某些设备中 - Objective C

c# - 如何在不使用JS的情况下打开新窗口

c# - 将 XML 数据集数据表合并为一个数据表

c# - 如何在启用 COM 互操作的 DLL 中引用 WCF 服务?