为类和协议创建Xamarin iOS绑定

时间:2014-08-01 13:16:02

标签: c# ios objective-c binding xamarin

目标

我们正在尝试编译路由器iOS SDK(Alpstein,MapBox或xmap)的最新分支,并从中创建一个Xamarin绑定项目。

我们已经尝试过的代码可以在这些存储库中找到(按照新鲜度的降序排列):

问题

不幸的是,我们陷入了初期阶段。 route-me需要一个TileSource来提供要在画布上绘制的图块。因此,我们需要通过绑定将RMAbstractWebMapSource类公开给我们的C#Xamarin客户端代码。由于此类继承自RMAbstractMercatorTileSource类,因此我们也需要绑定该类。最后,我们必须绑定RMAbstractMercatorTileSource实现的RMTileSource协议。

以下是Objective-C源中相关类和协议的定义:

RMAbstractWebMapSource

RMAbstractWebMapSource.h中定义的抽象类

@interface RMAbstractWebMapSource : RMAbstractMercatorTileSource

RMAbstractMercatorTileSource

RMAbstractMercatorTileSource.h中定义的抽象类

@interface RMAbstractMercatorTileSource : NSObject <RMTileSource>

RMTileSource

RMTileSource.h中定义的协议

@protocol RMTileSource <NSObject>

C#-Bindings

[BaseType (typeof (RMAbstractMercatorTileSource))]
public partial interface RMAbstractWebMapSource { ... }

[BaseType (typeof (NSObject))]
public partial interface RMAbstractMercatorTileSource : RMTileSource { ... }

[Model, Protocol, BaseType (typeof (NSObject))]
public partial interface RMTileSource { ... }

这些Bindings编译得很好。但是在运行时......

客户端代码使用

RMAbstractWebMapSource tileSource = new MyTileSource(1234);

MyTileSource定义为:

public sealed class MyTileSource: RMAbstractWebMapSource { ... }

错误

在实例化MyTileSource对象(构造函数调用)时会抛出以下运行时错误,同时导致应用程序崩溃:

NSForwarding: warning: object [0x...] of class 'MyProject_MyTileSource' does not implement methodSignatureForSelector: -- trouble ahead
NSForwarding: warning: object [0x...] of class 'MyProject_MyTileSource' does not implement doesNotRecognizeSelector: -- abort

路线

提前麻烦

可以通过Google找到此错误消息(例如http://www.touch-code-magazine.com/does-not-implement-methodsignatureforselector-trouble-ahead/)。网上找到的答案表明继承存在问题。看起来好像MyTileSource类没有继承NSObject。但是,来自Xamarin Bindings项目的生成代码(在构建之后在ProjectDir / obj中找到)建议不这样做:

public unsafe abstract partial class RMAbstractWebMapSource : RMAbstractMercatorTileSource { ... }
public unsafe partial class RMAbstractMercatorTileSource : NSObject, IRMTileSource { ... }
public unsafe partial class RMTileSource : NSObject, IRMTileSource { ... }
public interface IRMTileSource : INativeObject, IDisposable { ... }

选择

我们无法确定哪个选择器失败了。试图覆盖MyTileSource中的void DoesNotRecognizeSelector(Selector sel)会产生一个模糊的错误:

NSForwarding: warning: object [0x...] of class 'MyProject_MyTileSource' does not implement methodSignatureForSelector: -- trouble ahead
...(200x)...
NSForwarding: warning: object [0x...] of class 'MyProject_MyTileSource' does not implement methodSignatureForSelector: -- trouble ahead

最后,本机代码崩溃并出现分段错误(SIGSEGV)。我们这次也会从单声道运行时获得一个堆栈跟踪。它主要从调用MyTileSource的构造函数开始,并在NSObject中死掉,据我们所知:

mono-rt:   at <unknown> <0xffffffff>
mono-rt:   at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging.intptr_objc_msgSend (intptr,intptr) <IL 0x00026, 0xffffffff>
mono-rt:   at MonoTouch.Foundation.NSObject.AllocIfNeeded () [0x00015] in /Developer/MonoTouch/Source/maccore/src/Foundation/NSObject2.cs:390
mono-rt:   at MonoTouch.Foundation.NSObject..ctor (MonoTouch.Foundation.NSObjectFlag) [0x00006] in /Developer/MonoTouch/Source/maccore/src/Foundation/NSObject2.cs:102
mono-rt:   at XMap.RMAbstractMercatorTileSource..ctor (MonoTouch.Foundation.NSObjectFlag) <IL 0x00002, 0x0002b>
mono-rt:   at XMap.RMAbstractWebMapSource..ctor () <IL 0x00006, 0x00033>
mono-rt:   at Saalplan.RxTileSource..ctor (int) [0x00000] in /Users/rxDeveloper/Projects/rx.app.seatingmap/Xamarin.iOS/RxTileSource.cs:12
mono-rt:   at Saalplan.TileViewController.InitMapView () [0x00006] in /Users/rxDeveloper/Projects/rx.app.seatingmap/Xamarin.iOS/TileViewController.cs:24
mono-rt:   at Saalplan.TileViewController.ViewDidLoad () [0x00008] in /Users/rxDeveloper/Projects/rx.app.seatingmap/Xamarin.iOS/

问题

绑定这种继承和协议实现的组合的正确方法是什么?

3 个答案:

答案 0 :(得分:0)

您是否看过现有的monotouch绑定示例?你可以在这里找到它:

https://github.com/mono/monotouch-bindings/tree/master/Route-Me

答案 1 :(得分:0)

我们现在正在使用绑定工作。问题是我们的linkwith.cs文件。使用上面的绑定和以下linkwith.cs文件工作:

[assembly: LinkWith ("libXMap.a", LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Simulator, Frameworks = "CoreLocation QuartzCore UIKit Foundation CoreGraphics", LinkerFlags = "-lz -lsqlite3", ForceLoad = true, IsCxx = true)]

答案 2 :(得分:0)

对于遇到这个问题的其他人来说,这是值得的。我的问题是我的linkwith.cs文件没有包含LinkTarget.Simulator64。我得到类yyy的错误对象xxx没有实现methodSignatureForSelector: - 麻烦提前消息。