为 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
属性
更新
我误解了 NoDefaultValue
和 DefaultValueFromArgument
属性,它们在委托(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/