Xamarin.iOS中的自定义SQLite函数

我正在Xamarin.iOS上处理Sqlite的自定义函数。 我从这里得到的答案: 在给定的半径(Xamarin.Android)在地图上显示标记,但我遇到了问题

尝试使用–aot-only运行时JIT编译方法'(包装本机到托pipe)Mono.Data.Sqlite.SqliteFunction:ScalarCallback(intptr,int,intptr)'。

在栈上search后,我发现这里是一个解决scheme: 自定义函数SQLite与单声道,但解决scheme提到有我很难理解。

我不知道如何使用MonoPInvokeCallbackAttribute注释方法,并将其设置为静态,因为SqliteFunction类中的方法被覆盖,所以不能使其为静态。 如果有人能够帮助我理解该解决scheme或提供解决scheme中缺less的步骤,那将是非常好的。

我使用stream行的sqlite-net (Frank A. Krueger),然后使用SQLitePCLRaw.bundle_greenSQLitePCL.raw (都是Eric Sink)。

因此,您可以使用基于SQLitePCLRaw.ugly的API轻松设置和访问SQLite UDF。

基于Xamarin.iOSSQLite用户定义函数( UDF ):

 delegate void SQLiteCallback(sqlite3_context ctx, object user_data, sqlite3_value[] args); [MonoPInvokeCallback(typeof(SQLiteCallback))] static void UDFDistanceFunction(sqlite3_context ctx, object user_data, sqlite3_value[] args) { double radius = 6367; var lat1 = raw.sqlite3_value_double(args[0]); var lng1 = raw.sqlite3_value_double(args[1]); var lat2 = raw.sqlite3_value_double(args[2]); var lng2 = raw.sqlite3_value_double(args[3]); var result = radius * 2 * Math.Asin(Math.Min(1, Math.Sqrt((Math.Pow(Math.Sin((lat2 * (Math.PI / 180) - lat1 * (Math.PI / 180)) / 2.0), 2.0) + Math.Cos(lat1 * (Math.PI / 180)) * Math.Cos(lat2 * (Math.PI / 180)) * Math.Pow(Math.Sin((lng2 * (Math.PI / 180) - lng1 * (Math.PI / 180)) / 2.0), 2.0))))); raw.sqlite3_result_double(ctx, result); } 

用法:

使用sqlite-net-pcl来设置表,加载/更新数据,…..

 SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3()); var dbName = Path.Combine(Path.GetTempPath(), "StackOverflow.db"); var db = new SQLiteConnection(dbName, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create, true); db.CreateTable<BarLocations>(); db.Insert(new BarLocations() { name = "FOOBAR", lat = 47.60357, lng = -122.3295 }); 

使用SQLitePCLRaw.ugly来创build和查询SQLite UDF

 SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3()); var dbName = Path.Combine(Path.GetTempPath(), "StackOverflow.db"); using (sqlite3 dbRaw = ugly.open(dbName)) { dbRaw.create_function("distance", 4, null, UDFDistanceFunction); double currentLatitude = 47.0; double currentLongitude = -122.0; var sql = $"SELECT * FROM barlocations WHERE distance('{currentLatitude.ToString()}', '{currentLongitude.ToString()}', barlocations.lat, barlocations.lng) <= 100 ;"; var locs = dbRaw.query<BarLocations>(sql); foreach (var loc in locs) { Console.WriteLine(loc.name); } }