【问题标题】:Difficulty binding iOS delegate method without parameters没有参数的iOS委托方法难以绑定
【发布时间】:2015-07-06 17:40:39
【问题描述】:

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

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

}

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

编译器抱怨// @optional -(void)CaptureComplete; 和各自的绑定CaptureComplete() 没有参数并且它至少需要一个。

问:我需要做什么来绑定这个委托?

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

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

更新

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

【问题讨论】:

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


    【解决方案1】:

    我找到了解决办法。

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

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

    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 错误消息所示。

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

    // @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 接口的实现。

    例如

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

    【讨论】:

      【解决方案2】:

      “CaptureComplete:”可能正在等待发件人?

      【讨论】:

      • 这就是我的想法,但是 ObjC 签名并不表明它确实如此。我尝试向托管方法添加一个参数,但随后又产生了另一个 registrar found a signature mismatch in the method 错误。
      • 我已将: 添加到[Export()],现在可以编译了。
      • 这很遗憾在运行时失败,ObjCRuntime.RuntimeException: Wrapper type 'Device.SomeDeviceDelegate' is missing its native ObjectiveC class 'SomeDeviceDelegate'.
      • 这不是解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-05
      • 1970-01-01
      • 1970-01-01
      • 2016-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多