Мы пытаемся скомпилировать недавнюю вилку маршрута IOS SDK (Alpstein, MapBox или xmap) и создать проект привязки Xamarin.
Код, который мы уже пробовали, можно найти в этих репозиториях (в порядке убывания свежести):
К сожалению, мы застряли на довольно начальной стадии. route-me нуждается в TileSource для предоставления плиток, которые нужно нарисовать на холсте. Поэтому нам нужно подвергнуть класс RMAbstractWebMapSource нашему клиентскому коду С# Xamarin с помощью привязок. Поскольку этот класс наследуется от класса RMAbstractMercatorTileSource, нам также необходимо связать его. Наконец, мы должны привязать протокол RMTileSource, который реализует RMAbstractMercatorTileSource.
Ниже приведены определения соответствующих классов и протоколов в источнике Objective-C:
Абстрактный класс, определенный в RMAbstractWebMapSource.h
@interface RMAbstractWebMapSource : RMAbstractMercatorTileSource
Абстрактный класс, определенный в RMAbstractMercatorTileSource.h
@interface RMAbstractMercatorTileSource : NSObject <RMTileSource>
Протокол, определенный в RMTileSource.h
@protocol RMTileSource <NSObject>
[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 { ... }
Мы не смогли определить, какой селектор не удалось. Попытка переопределить void DoNotRecognizeSelector (Селектор sel) в MyTileSource дает смутную ошибку:
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). На этот раз мы все равно получаем стекную трассировку из моно-runtime. Он в основном начинается с вызова конструктора 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/
Каков правильный способ привязки этой комбинации наследования и реализации протокола?
Для чего это стоит для других, сталкивающихся с этим. Моя проблема заключалась в том, что мой файл linkwith.cs не содержал LinkTarget.Simulator64. Я получаю объект ошибки xxx класса yyy не реализует методSignatureForSelector: - сообщение о неисправности вперед.
Теперь у нас есть привязки. Проблема заключалась в нашем файле 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)]
Вы посмотрели существующий пример привязки к моноточку? Вы можете найти это здесь:
https://github.com/mono/monotouch-bindings/tree/master/Route-Me